mirror of
https://github.com/IntellectualSites/PlotSquared.git
synced 2025-06-25 02:04:44 +02:00
Updated Gradle
This commit is contained in:
26
Bukkit/build.gradle
Normal file
26
Bukkit/build.gradle
Normal file
@ -0,0 +1,26 @@
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'idea'
|
||||
|
||||
dependencies {
|
||||
compile project(':Core')
|
||||
compile 'org.bukkit:bukkit:1.8.8-R0.1-SNAPSHOT'
|
||||
compile 'net.milkbowl.vault:VaultAPI:1.5'
|
||||
}
|
||||
|
||||
processResources {
|
||||
from('src/main/resources') {
|
||||
include 'plugin.yml'
|
||||
expand(
|
||||
name: project.parent.name,
|
||||
version: project.parent.version
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
dependencies {
|
||||
include(dependency(':Core'))
|
||||
}
|
||||
}
|
||||
|
||||
build.dependsOn(shadowJar)
|
@ -0,0 +1,758 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.intellectualcrafters.plot.api;
|
||||
|
||||
import com.intellectualcrafters.configuration.file.YamlConfiguration;
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.commands.MainCommand;
|
||||
import com.intellectualcrafters.plot.commands.SubCommand;
|
||||
import com.intellectualcrafters.plot.config.C;
|
||||
import com.intellectualcrafters.plot.flag.AbstractFlag;
|
||||
import com.intellectualcrafters.plot.flag.FlagManager;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotArea;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
import com.intellectualcrafters.plot.object.PlotManager;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.util.ChunkManager;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler;
|
||||
import com.intellectualcrafters.plot.util.SetQueue;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandler;
|
||||
import com.intellectualcrafters.plot.uuid.UUIDWrapper;
|
||||
import com.plotsquared.bukkit.util.BukkitUtil;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* PlotSquared API
|
||||
*
|
||||
|
||||
|
||||
* @version API 2.0
|
||||
*
|
||||
*/
|
||||
|
||||
public class PlotAPI {
|
||||
|
||||
/**
|
||||
* Permission that allows for admin access, this permission node will allow the player to use any part of the
|
||||
* plugin, without limitations.
|
||||
* @deprecated Use C.PERMISSION_ADMIN.s() instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String ADMIN_PERMISSION = C.PERMISSION_ADMIN.s();
|
||||
|
||||
/**
|
||||
* @deprecated Use new PlotAPI() instead
|
||||
*/
|
||||
@Deprecated
|
||||
public PlotAPI(final JavaPlugin plugin) {}
|
||||
|
||||
/**
|
||||
* @see PS
|
||||
*
|
||||
* @deprecated Use this class if you just want to do a few simple things.<br>
|
||||
* - It will remain stable for future versions of the plugin
|
||||
* - The PlotPlayer and Plot class should be considered relatively safe
|
||||
* - For more advanced/intensive tasks you should consider using other classes
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public PlotAPI() {}
|
||||
|
||||
/**
|
||||
* Get all plots
|
||||
*
|
||||
* @return all plots
|
||||
*
|
||||
* @see PS#getPlots()
|
||||
*/
|
||||
public Set<Plot> getAllPlots() {
|
||||
return PS.get().getPlots();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all plots for a player
|
||||
*
|
||||
* @param player Player, whose plots to search for
|
||||
*
|
||||
* @return all plots that a player owns
|
||||
*/
|
||||
public Set<Plot> getPlayerPlots(final Player player) {
|
||||
return PS.get().getPlots(BukkitUtil.getPlayer(player));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a plot world
|
||||
*
|
||||
* @param plotArea Plot World Object
|
||||
* @see PS#addPlotArea(PlotArea)
|
||||
*/
|
||||
public void addPlotArea(final PlotArea plotArea) {
|
||||
PS.get().addPlotArea(plotArea);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return main configuration
|
||||
*
|
||||
* @see PS#config
|
||||
*/
|
||||
public YamlConfiguration getConfig() {
|
||||
return PS.get().config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return storage configuration
|
||||
*
|
||||
* @see PS#storage
|
||||
*/
|
||||
public YamlConfiguration getStorage() {
|
||||
return PS.get().storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the main class for this plugin <br> - Contains a lot of fields and methods - not very well organized <br>
|
||||
* Only use this if you really need it
|
||||
*
|
||||
* @return PlotSquared PlotSquared Main Class
|
||||
*
|
||||
* @see PS
|
||||
*/
|
||||
public PS getMain() {
|
||||
return PS.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* ChunkManager class contains several useful methods<br>
|
||||
* - Chunk deletion<br>
|
||||
* - Moving or copying regions<br>
|
||||
* - plot swapping<br>
|
||||
* - Entity tracking<br>
|
||||
* - region regeneration<br>
|
||||
*
|
||||
* @return ChunkManager
|
||||
*
|
||||
* @see com.intellectualcrafters.plot.util.ChunkManager
|
||||
*/
|
||||
public ChunkManager getChunkManager() {
|
||||
return ChunkManager.manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block/biome set queue
|
||||
* @return SetQueue.IMP
|
||||
*/
|
||||
public SetQueue getSetQueue() {
|
||||
return SetQueue.IMP;
|
||||
}
|
||||
|
||||
/**
|
||||
* UUIDWrapper class has basic methods for getting UUIDS (it's recommended to use the UUIDHandler class instead)
|
||||
*
|
||||
* @return UUIDWrapper
|
||||
*
|
||||
* @see com.intellectualcrafters.plot.uuid.UUIDWrapper
|
||||
*/
|
||||
public UUIDWrapper getUUIDWrapper() {
|
||||
return UUIDHandler.getUUIDWrapper();
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not use this. Instead use FlagManager.[method] in your code.
|
||||
* - Flag related stuff
|
||||
*
|
||||
* @return FlagManager
|
||||
*
|
||||
* @see com.intellectualcrafters.plot.flag.FlagManager
|
||||
*/
|
||||
@Deprecated
|
||||
public FlagManager getFlagManager() {
|
||||
return new FlagManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not use this. Instead use MainUtil.[method] in your code.
|
||||
* - Basic plot management stuff
|
||||
*
|
||||
* @return MainUtil
|
||||
*
|
||||
* @see MainUtil
|
||||
*/
|
||||
@Deprecated
|
||||
public MainUtil getMainUtil() {
|
||||
return new MainUtil();
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not use this. Instead use C.PERMISSION_[method] in your code.
|
||||
* - Basic permission management stuff
|
||||
*
|
||||
* @return Array of strings
|
||||
*
|
||||
* @see com.intellectualcrafters.plot.util.Permissions
|
||||
*/
|
||||
@Deprecated
|
||||
public String[] getPermissions() {
|
||||
final ArrayList<String> perms = new ArrayList<>();
|
||||
for (final C c : C.values()) {
|
||||
if ("static.permissions".equals(c.getCat())) {
|
||||
perms.add(c.s());
|
||||
}
|
||||
}
|
||||
return perms.toArray(new String[perms.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* SchematicHandler class contains methods related to pasting, reading and writing schematics
|
||||
*
|
||||
* @return SchematicHandler
|
||||
*
|
||||
* @see com.intellectualcrafters.plot.util.SchematicHandler
|
||||
*/
|
||||
public SchematicHandler getSchematicHandler() {
|
||||
return SchematicHandler.manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use C.[caption] instead
|
||||
*
|
||||
* @return C
|
||||
*
|
||||
* @see com.intellectualcrafters.plot.config.C
|
||||
*/
|
||||
@Deprecated
|
||||
public C[] getCaptions() {
|
||||
return C.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plot manager for a world. - Most of these methods can be accessed through the MainUtil
|
||||
*
|
||||
* @param world Which manager to get
|
||||
*
|
||||
* @return PlotManager
|
||||
*
|
||||
* @see com.intellectualcrafters.plot.object.PlotManager
|
||||
* @see PS#getPlotManager(Plot)
|
||||
*/
|
||||
@Deprecated
|
||||
public PlotManager getPlotManager(final World world) {
|
||||
if (world == null) {
|
||||
return null;
|
||||
}
|
||||
return getPlotManager(world.getName());
|
||||
}
|
||||
|
||||
public Set<PlotArea> getPlotAreas(World world) {
|
||||
if (world == null) {
|
||||
return new HashSet<>();
|
||||
}
|
||||
return PS.get().getPlotAreas(world.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plot manager for a world. - Contains useful low level methods for plot merging, clearing, and
|
||||
* tessellation
|
||||
*
|
||||
* @param world
|
||||
*
|
||||
* @return PlotManager
|
||||
*
|
||||
* @see PS#getPlotManager(Plot)
|
||||
* @see com.intellectualcrafters.plot.object.PlotManager
|
||||
*/
|
||||
@Deprecated
|
||||
public PlotManager getPlotManager(final String world) {
|
||||
Set<PlotArea> areas = PS.get().getPlotAreas(world);
|
||||
switch (areas.size()) {
|
||||
case 0:
|
||||
return null;
|
||||
case 1:
|
||||
return areas.iterator().next().manager;
|
||||
default:
|
||||
PS.debug("PlotAPI#getPlotManager(org.bukkit.World) is deprecated and doesn't support multi plot area worlds.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings for a world (settings bundled in PlotArea class) - You will need to downcast for the specific
|
||||
* settings a Generator has. e.g. DefaultPlotWorld class implements PlotArea
|
||||
*
|
||||
* @param world (to get settings of)
|
||||
*
|
||||
* @return PlotArea class for that world ! will return null if not a plot world world
|
||||
*
|
||||
* @see #getPlotAreas(World)
|
||||
* @see com.intellectualcrafters.plot.object.PlotArea
|
||||
*/
|
||||
@Deprecated
|
||||
public PlotArea getWorldSettings(final World world) {
|
||||
if (world == null) {
|
||||
return null;
|
||||
}
|
||||
return getWorldSettings(world.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings for a world (settings bundled in PlotArea class)
|
||||
*
|
||||
* @param world (to get settings of)
|
||||
*
|
||||
* @return PlotArea class for that world ! will return null if not a plot world world
|
||||
*
|
||||
* @see PS#getPlotArea(String, String)
|
||||
* @see com.intellectualcrafters.plot.object.PlotArea
|
||||
*/
|
||||
@Deprecated
|
||||
public PlotArea getWorldSettings(final String world) {
|
||||
if (world == null) {
|
||||
return null;
|
||||
}
|
||||
Set<PlotArea> areas = PS.get().getPlotAreas(world);
|
||||
switch (areas.size()) {
|
||||
case 0:
|
||||
return null;
|
||||
case 1:
|
||||
return areas.iterator().next();
|
||||
default:
|
||||
PS.debug("PlotAPI#getWorldSettings(org.bukkit.World) is deprecated and doesn't support multi plot area worlds.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to a player.
|
||||
*
|
||||
* @param player Player that will receive the message
|
||||
* @param c (Caption)
|
||||
*
|
||||
* @see MainUtil#sendMessage(PlotPlayer, C, String...)
|
||||
* com.intellectualcrafters.plot.config.C, String...)
|
||||
*/
|
||||
public void sendMessage(final Player player, final C c) {
|
||||
MainUtil.sendMessage(BukkitUtil.getPlayer(player), c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to a player. - Supports color codes
|
||||
*
|
||||
* @param player Player that will receive the message
|
||||
* @param string The message
|
||||
*
|
||||
* @see MainUtil#sendMessage(PlotPlayer, String)
|
||||
*/
|
||||
public void sendMessage(final Player player, final String string) {
|
||||
MainUtil.sendMessage(BukkitUtil.getPlayer(player), string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to the console. - Supports color codes
|
||||
*
|
||||
* @param msg Message that should be sent to the console
|
||||
*
|
||||
* @see MainUtil#sendConsoleMessage(C, String...)
|
||||
*/
|
||||
public void sendConsoleMessage(final String msg) {
|
||||
PS.log(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to the console
|
||||
*
|
||||
* @param c (Caption)
|
||||
*
|
||||
* @see #sendConsoleMessage(String)
|
||||
* @see com.intellectualcrafters.plot.config.C
|
||||
*/
|
||||
public void sendConsoleMessage(final C c) {
|
||||
sendConsoleMessage(c.s());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a flag for use in plots
|
||||
*
|
||||
* @param flag Flag that should be registered
|
||||
*
|
||||
* @see com.intellectualcrafters.plot.flag.FlagManager#addFlag(com.intellectualcrafters.plot.flag.AbstractFlag)
|
||||
* @see com.intellectualcrafters.plot.flag.AbstractFlag
|
||||
*/
|
||||
public void addFlag(final AbstractFlag flag) {
|
||||
FlagManager.addFlag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* get all the currently registered flags
|
||||
*
|
||||
* @return array of Flag[]
|
||||
*
|
||||
* @see com.intellectualcrafters.plot.flag.FlagManager#getFlags()
|
||||
* @see com.intellectualcrafters.plot.flag.AbstractFlag
|
||||
*/
|
||||
public AbstractFlag[] getFlags() {
|
||||
return FlagManager.getFlags().toArray(new AbstractFlag[FlagManager.getFlags().size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a plot based on the ID
|
||||
*
|
||||
* @param world World in which the plot is located
|
||||
* @param x Plot Location X Co-ord
|
||||
* @param z Plot Location Z Co-ord
|
||||
*
|
||||
* @return plot, null if ID is wrong
|
||||
*
|
||||
* @see PlotArea#getPlot(PlotId)
|
||||
*/
|
||||
@Deprecated
|
||||
public Plot getPlot(final World world, final int x, final int z) {
|
||||
if (world == null) {
|
||||
return null;
|
||||
}
|
||||
PlotArea area = getWorldSettings(world);
|
||||
if (area == null) {
|
||||
return null;
|
||||
}
|
||||
return area.getPlot(new PlotId(x, z));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a plot based on the location
|
||||
*
|
||||
* @param l The location that you want to to retrieve the plot from
|
||||
*
|
||||
* @return plot if found, otherwise it creates a temporary plot-
|
||||
*
|
||||
* @see Plot
|
||||
*/
|
||||
public Plot getPlot(final Location l) {
|
||||
if (l == null) {
|
||||
return null;
|
||||
}
|
||||
return BukkitUtil.getLocation(l).getPlot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a plot based on the player location
|
||||
*
|
||||
* @param player Get the current plot for the player location
|
||||
*
|
||||
* @return plot if found, otherwise it creates a temporary plot
|
||||
*
|
||||
* @see #getPlot(org.bukkit.Location)
|
||||
* @see Plot
|
||||
*/
|
||||
public Plot getPlot(final Player player) {
|
||||
return this.getPlot(player.getLocation());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not a player has a plot
|
||||
*
|
||||
* @param player Player that you want to check for
|
||||
*
|
||||
* @return true if player has a plot, false if not.
|
||||
*
|
||||
* @see #getPlots(World, Player, boolean)
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean hasPlot(final World world, final Player player) {
|
||||
return getPlots(world, player, true) != null && getPlots(world, player, true).length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all plots for the player
|
||||
*
|
||||
* @param plr to search for
|
||||
* @param just_owner should we just search for owner? Or with rights?
|
||||
*/
|
||||
@Deprecated
|
||||
public Plot[] getPlots(final World world, final Player plr, final boolean just_owner) {
|
||||
final ArrayList<Plot> pPlots = new ArrayList<>();
|
||||
UUID uuid = BukkitUtil.getPlayer(plr).getUUID();
|
||||
for (final Plot plot : PS.get().getPlots(world.getName())) {
|
||||
if (just_owner) {
|
||||
if (plot.hasOwner() && plot.isOwner(uuid)) {
|
||||
pPlots.add(plot);
|
||||
}
|
||||
} else {
|
||||
if (plot.isAdded(uuid)) {
|
||||
pPlots.add(plot);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pPlots.toArray(new Plot[pPlots.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all plots for the world
|
||||
*
|
||||
* @param world to get plots of
|
||||
*
|
||||
* @return Plot[] - array of plot objects in world
|
||||
*
|
||||
* @see PS#getPlots(String)
|
||||
* @see Plot
|
||||
*/
|
||||
@Deprecated
|
||||
public Plot[] getPlots(final World world) {
|
||||
if (world == null) {
|
||||
return new Plot[0];
|
||||
}
|
||||
Collection<Plot> plots = PS.get().getPlots(world.getName());
|
||||
return plots.toArray(new Plot[plots.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all plot worlds
|
||||
*
|
||||
* @return World[] - array of plot worlds
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public String[] getPlotWorlds() {
|
||||
Set<String> plotWorldStrings = PS.get().getPlotWorldStrings();
|
||||
return plotWorldStrings.toArray(new String[plotWorldStrings.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if plot world
|
||||
*
|
||||
* @param world (to check if plot world)
|
||||
*
|
||||
* @return boolean (if plot world or not)
|
||||
*
|
||||
* @see PS#hasPlotArea(String)
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isPlotWorld(final World world) {
|
||||
return PS.get().hasPlotArea(world.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plot locations
|
||||
*
|
||||
* @param p Plot that you want to get the locations for
|
||||
*
|
||||
* @return [0] = bottomLc, [1] = topLoc, [2] = home
|
||||
*
|
||||
* @deprecated As merged plots may not have a rectangular shape
|
||||
*
|
||||
* @see Plot
|
||||
*/
|
||||
@Deprecated
|
||||
public Location[] getLocations(final Plot p) {
|
||||
return new Location[] { BukkitUtil.getLocation(p.getBottom()), BukkitUtil.getLocation(p.getTop()), BukkitUtil.getLocation(p.getHome()) };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get home location
|
||||
*
|
||||
* @param p Plot that you want to get the location for
|
||||
*
|
||||
* @return plot bottom location
|
||||
*
|
||||
* @see Plot
|
||||
*/
|
||||
public Location getHomeLocation(final Plot p) {
|
||||
return BukkitUtil.getLocation(p.getHome());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Bottom Location (min, min, min)
|
||||
*
|
||||
* @param p Plot that you want to get the location for
|
||||
*
|
||||
* @return plot bottom location
|
||||
*
|
||||
* @deprecated As merged plots may not have a rectangular shape
|
||||
*
|
||||
* @see Plot
|
||||
*/
|
||||
@Deprecated
|
||||
public Location getBottomLocation(final Plot p) {
|
||||
return BukkitUtil.getLocation(p.getBottom());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Top Location (max, max, max)
|
||||
*
|
||||
* @param p Plot that you want to get the location for
|
||||
*
|
||||
* @return plot top location
|
||||
*
|
||||
* @deprecated As merged plots may not have a rectangular shape
|
||||
*
|
||||
* @see Plot
|
||||
*/
|
||||
@Deprecated
|
||||
public Location getTopLocation(final Plot p) {
|
||||
return BukkitUtil.getLocation(p.getTop());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not a player is in a plot
|
||||
*
|
||||
* @param player who we're checking for
|
||||
*
|
||||
* @return true if the player is in a plot, false if not-
|
||||
*
|
||||
*/
|
||||
public boolean isInPlot(final Player player) {
|
||||
return getPlot(player) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a subcommand
|
||||
*
|
||||
* @param c SubCommand, that we want to register
|
||||
*
|
||||
* @see com.intellectualcrafters.plot.commands.SubCommand
|
||||
*/
|
||||
public void registerCommand(final SubCommand c) {
|
||||
if (c.getCommand() != null) {
|
||||
MainCommand.getInstance().addCommand(c);
|
||||
} else {
|
||||
MainCommand.getInstance().createCommand(c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PlotSquared class
|
||||
*
|
||||
* @return PlotSquared Class
|
||||
*
|
||||
* @see PS
|
||||
*/
|
||||
public PS getPlotSquared() {
|
||||
return PS.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player plot count
|
||||
*
|
||||
* @param world Specify the world we want to select the plots from
|
||||
* @param player Player, for whom we're getting the plot count
|
||||
*
|
||||
* @return the number of plots the player has
|
||||
*
|
||||
*/
|
||||
public int getPlayerPlotCount(final World world, final Player player) {
|
||||
if (world == null) {
|
||||
return 0;
|
||||
}
|
||||
return BukkitUtil.getPlayer(player).getPlotCount(world.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection containing the players plots
|
||||
*
|
||||
* @param world Specify the world we want to select the plots from
|
||||
* @param player Player, for whom we're getting the plots
|
||||
*
|
||||
* @return a set containing the players plots
|
||||
*
|
||||
* @see PS#getPlots(String, PlotPlayer)
|
||||
*
|
||||
* @see Plot
|
||||
*/
|
||||
public Set<Plot> getPlayerPlots(final World world, final Player player) {
|
||||
if (world == null) {
|
||||
return new HashSet<>();
|
||||
}
|
||||
return BukkitUtil.getPlayer(player).getPlots(world.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the numbers of plots, which the player is able to build in
|
||||
*
|
||||
* @param player Player, for whom we're getting the plots (trusted, member and owner)
|
||||
*
|
||||
* @return the number of allowed plots
|
||||
*
|
||||
*/
|
||||
public int getAllowedPlots(final Player player) {
|
||||
final PlotPlayer pp = BukkitUtil.getPlayer(player);
|
||||
return pp.getAllowedPlots();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PlotPlayer for a player<br>
|
||||
* - The PlotPlayer is usually cached and will provide useful functions relating to players
|
||||
*
|
||||
* @see PlotPlayer#wrap(Object)
|
||||
*
|
||||
* @param player
|
||||
* @return
|
||||
*/
|
||||
public PlotPlayer wrapPlayer(final Player player) {
|
||||
return PlotPlayer.wrap(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PlotPlayer for a UUID (Please note that PlotSquared can be configured to provide different UUIDs than bukkit)
|
||||
*
|
||||
* @see PlotPlayer#wrap(Object)
|
||||
*
|
||||
* @param uuid
|
||||
* @return
|
||||
*/
|
||||
public PlotPlayer wrapPlayer(final UUID uuid) {
|
||||
return PlotPlayer.wrap(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PlotPlayer for a username
|
||||
*
|
||||
* @see PlotPlayer#wrap(Object)
|
||||
*
|
||||
* @param player
|
||||
* @return
|
||||
*/
|
||||
public PlotPlayer wrapPlayer(final String player) {
|
||||
return PlotPlayer.wrap(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PlotPlayer for an offline player<br>
|
||||
* Note that this will work if the player is offline, however not all functionality will work
|
||||
*
|
||||
* @see PlotPlayer#wrap(Object)
|
||||
*
|
||||
* @param player
|
||||
* @return
|
||||
*/
|
||||
public PlotPlayer wrapPlayer(final OfflinePlayer player) {
|
||||
return PlotPlayer.wrap(player);
|
||||
}
|
||||
}
|
705
Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java
Normal file
705
Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java
Normal file
@ -0,0 +1,705 @@
|
||||
package com.plotsquared.bukkit;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.intellectualcrafters.configuration.ConfigurationSection;
|
||||
import com.intellectualcrafters.plot.IPlotMain;
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.commands.MainCommand;
|
||||
import com.intellectualcrafters.plot.config.C;
|
||||
import com.intellectualcrafters.plot.config.ConfigurationNode;
|
||||
import com.intellectualcrafters.plot.config.Settings;
|
||||
import com.intellectualcrafters.plot.flag.FlagManager;
|
||||
import com.intellectualcrafters.plot.generator.GeneratorWrapper;
|
||||
import com.intellectualcrafters.plot.generator.HybridGen;
|
||||
import com.intellectualcrafters.plot.generator.HybridUtils;
|
||||
import com.intellectualcrafters.plot.generator.IndependentPlotGenerator;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotArea;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.RunnableVal;
|
||||
import com.intellectualcrafters.plot.object.SetupObject;
|
||||
import com.intellectualcrafters.plot.util.AbstractTitle;
|
||||
import com.intellectualcrafters.plot.util.ChatManager;
|
||||
import com.intellectualcrafters.plot.util.ChunkManager;
|
||||
import com.intellectualcrafters.plot.util.ConsoleColors;
|
||||
import com.intellectualcrafters.plot.util.EconHandler;
|
||||
import com.intellectualcrafters.plot.util.EventUtil;
|
||||
import com.intellectualcrafters.plot.util.InventoryUtil;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.PlotQueue;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler;
|
||||
import com.intellectualcrafters.plot.util.SetupUtils;
|
||||
import com.intellectualcrafters.plot.util.StringMan;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandler;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandlerImplementation;
|
||||
import com.intellectualcrafters.plot.util.WorldUtil;
|
||||
import com.intellectualcrafters.plot.uuid.UUIDWrapper;
|
||||
import com.plotsquared.bukkit.commands.DebugUUID;
|
||||
import com.plotsquared.bukkit.database.plotme.ClassicPlotMeConnector;
|
||||
import com.plotsquared.bukkit.database.plotme.LikePlotMeConverter;
|
||||
import com.plotsquared.bukkit.database.plotme.PlotMeConnector_017;
|
||||
import com.plotsquared.bukkit.generator.BukkitPlotGenerator;
|
||||
import com.plotsquared.bukkit.listeners.ChunkListener;
|
||||
import com.plotsquared.bukkit.listeners.ForceFieldListener;
|
||||
import com.plotsquared.bukkit.listeners.PlayerEvents;
|
||||
import com.plotsquared.bukkit.listeners.PlayerEvents_1_8;
|
||||
import com.plotsquared.bukkit.listeners.PlayerEvents_1_8_3;
|
||||
import com.plotsquared.bukkit.listeners.PlotPlusListener;
|
||||
import com.plotsquared.bukkit.listeners.WorldEvents;
|
||||
import com.plotsquared.bukkit.listeners.worldedit.WEListener;
|
||||
import com.plotsquared.bukkit.titles.DefaultTitle;
|
||||
import com.plotsquared.bukkit.util.BukkitChatManager;
|
||||
import com.plotsquared.bukkit.util.BukkitChunkManager;
|
||||
import com.plotsquared.bukkit.util.BukkitCommand;
|
||||
import com.plotsquared.bukkit.util.BukkitEconHandler;
|
||||
import com.plotsquared.bukkit.util.BukkitEventUtil;
|
||||
import com.plotsquared.bukkit.util.BukkitHybridUtils;
|
||||
import com.plotsquared.bukkit.util.BukkitInventoryUtil;
|
||||
import com.plotsquared.bukkit.util.BukkitPlainChatManager;
|
||||
import com.plotsquared.bukkit.util.BukkitSchematicHandler;
|
||||
import com.plotsquared.bukkit.util.BukkitSetupUtils;
|
||||
import com.plotsquared.bukkit.util.BukkitTaskManager;
|
||||
import com.plotsquared.bukkit.util.BukkitUtil;
|
||||
import com.plotsquared.bukkit.util.Metrics;
|
||||
import com.plotsquared.bukkit.util.SendChunk;
|
||||
import com.plotsquared.bukkit.util.SetGenCB;
|
||||
import com.plotsquared.bukkit.util.block.FastQueue_1_7;
|
||||
import com.plotsquared.bukkit.util.block.FastQueue_1_8;
|
||||
import com.plotsquared.bukkit.util.block.FastQueue_1_8_3;
|
||||
import com.plotsquared.bukkit.util.block.SlowQueue;
|
||||
import com.plotsquared.bukkit.uuid.DefaultUUIDWrapper;
|
||||
import com.plotsquared.bukkit.uuid.FileUUIDHandler;
|
||||
import com.plotsquared.bukkit.uuid.LowerOfflineUUIDWrapper;
|
||||
import com.plotsquared.bukkit.uuid.OfflineUUIDWrapper;
|
||||
import com.plotsquared.bukkit.uuid.SQLUUIDHandler;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
|
||||
public class BukkitMain extends JavaPlugin implements Listener, IPlotMain {
|
||||
|
||||
public static BukkitMain THIS;
|
||||
public static WorldEditPlugin worldEdit;
|
||||
|
||||
private int[] version;
|
||||
|
||||
@Override
|
||||
public int[] getServerVersion() {
|
||||
if (version == null) {
|
||||
try {
|
||||
version = new int[3];
|
||||
final String[] split = Bukkit.getBukkitVersion().split("-")[0].split("\\.");
|
||||
version[0] = Integer.parseInt(split[0]);
|
||||
version[1] = Integer.parseInt(split[1]);
|
||||
if (split.length == 3) {
|
||||
version[2] = Integer.parseInt(split[2]);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
e.printStackTrace();
|
||||
PS.debug(StringMan.getString(Bukkit.getBukkitVersion()));
|
||||
PS.debug(StringMan.getString(Bukkit.getBukkitVersion().split("-")[0].split("\\.")));
|
||||
return new int[]{Integer.MAX_VALUE, 0, 0};
|
||||
}
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
THIS = this;
|
||||
new PS(this, "Bukkit");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
PS.get().disable();
|
||||
Bukkit.getScheduler().cancelTasks(this);
|
||||
THIS = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String message) {
|
||||
if (message == null) {
|
||||
return;
|
||||
}
|
||||
if ((THIS != null) && (Bukkit.getServer().getConsoleSender() != null)) {
|
||||
try {
|
||||
message = C.color(message);
|
||||
if (!Settings.CONSOLE_COLOR) {
|
||||
message = ChatColor.stripColor(message);
|
||||
}
|
||||
Bukkit.getServer().getConsoleSender().sendMessage(message);
|
||||
return;
|
||||
} catch (final Throwable e) {}
|
||||
}
|
||||
System.out.println(ConsoleColors.fromString(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
if (THIS != null) {
|
||||
onDisable();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getPluginVersion() {
|
||||
final String[] split = getDescription().getVersion().split("\\.");
|
||||
return new int[] { Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2]) };
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerCommands() {
|
||||
final BukkitCommand bcmd = new BukkitCommand();
|
||||
final PluginCommand plotCommand = getCommand("plots");
|
||||
plotCommand.setExecutor(bcmd);
|
||||
plotCommand.setAliases(Arrays.asList("p", "ps", "plotme", "plot"));
|
||||
plotCommand.setTabCompleter(bcmd);
|
||||
MainCommand.getInstance().addCommand(new DebugUUID());
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDirectory() {
|
||||
return getDataFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getWorldContainer() {
|
||||
return Bukkit.getWorldContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskManager getTaskManager() {
|
||||
return new BukkitTaskManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runEntityTask() {
|
||||
log(C.PREFIX.s() + "KillAllEntities started.");
|
||||
TaskManager.runTaskRepeat(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PS.get().foreachPlotArea(new RunnableVal<PlotArea>() {
|
||||
@Override
|
||||
public void run(PlotArea pw) {
|
||||
World world = Bukkit.getWorld(pw.worldname);
|
||||
try {
|
||||
if (world == null) {
|
||||
return;
|
||||
}
|
||||
List<Entity> entities = world.getEntities();
|
||||
Iterator<Entity> iter = entities.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Entity entity = iter.next();
|
||||
switch (entity.getType()) {
|
||||
case EGG:
|
||||
case ENDER_CRYSTAL:
|
||||
case COMPLEX_PART:
|
||||
case FISHING_HOOK:
|
||||
case ENDER_SIGNAL:
|
||||
case EXPERIENCE_ORB:
|
||||
case LEASH_HITCH:
|
||||
case FIREWORK:
|
||||
case WEATHER:
|
||||
case LIGHTNING:
|
||||
case WITHER_SKULL:
|
||||
case UNKNOWN:
|
||||
case PLAYER: {
|
||||
// non moving / unremovable
|
||||
continue;
|
||||
}
|
||||
case THROWN_EXP_BOTTLE:
|
||||
case SPLASH_POTION:
|
||||
case SNOWBALL:
|
||||
case ENDER_PEARL:
|
||||
case ARROW: {
|
||||
// managed elsewhere | projectile
|
||||
continue;
|
||||
}
|
||||
case ARMOR_STAND:
|
||||
case ITEM_FRAME:
|
||||
case PAINTING: {
|
||||
// TEMPORARILY CLASSIFY AS VEHICLE
|
||||
}
|
||||
case MINECART:
|
||||
case MINECART_CHEST:
|
||||
case MINECART_COMMAND:
|
||||
case MINECART_FURNACE:
|
||||
case MINECART_HOPPER:
|
||||
case MINECART_MOB_SPAWNER:
|
||||
case MINECART_TNT:
|
||||
case BOAT: {
|
||||
if (!Settings.KILL_ROAD_VEHICLES) {
|
||||
continue;
|
||||
}
|
||||
com.intellectualcrafters.plot.object.Location loc = BukkitUtil.getLocation(entity.getLocation());
|
||||
Plot plot = loc.getPlot();
|
||||
if (plot == null) {
|
||||
if (loc.isPlotArea()) {
|
||||
iter.remove();
|
||||
entity.remove();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
List<MetadataValue> meta = entity.getMetadata("plot");
|
||||
if (meta.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
Plot origin = (Plot) meta.get(0).value();
|
||||
if (!plot.equals(origin.getBasePlot(false))) {
|
||||
iter.remove();
|
||||
entity.remove();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case SMALL_FIREBALL:
|
||||
case FIREBALL:
|
||||
case DROPPED_ITEM: {
|
||||
// dropped item
|
||||
continue;
|
||||
}
|
||||
case PRIMED_TNT:
|
||||
case FALLING_BLOCK: {
|
||||
// managed elsewhere
|
||||
continue;
|
||||
}
|
||||
case BAT:
|
||||
case BLAZE:
|
||||
case CAVE_SPIDER:
|
||||
case CHICKEN:
|
||||
case COW:
|
||||
case CREEPER:
|
||||
case ENDERMAN:
|
||||
case ENDERMITE:
|
||||
case ENDER_DRAGON:
|
||||
case GHAST:
|
||||
case GIANT:
|
||||
case GUARDIAN:
|
||||
case HORSE:
|
||||
case IRON_GOLEM:
|
||||
case MAGMA_CUBE:
|
||||
case MUSHROOM_COW:
|
||||
case OCELOT:
|
||||
case PIG:
|
||||
case PIG_ZOMBIE:
|
||||
case RABBIT:
|
||||
case SHEEP:
|
||||
case SILVERFISH:
|
||||
case SKELETON:
|
||||
case SLIME:
|
||||
case SNOWMAN:
|
||||
case SPIDER:
|
||||
case SQUID:
|
||||
case VILLAGER:
|
||||
case WITCH:
|
||||
case WITHER:
|
||||
case WOLF:
|
||||
case ZOMBIE:
|
||||
default: {
|
||||
if (!Settings.KILL_ROAD_MOBS) {
|
||||
continue;
|
||||
}
|
||||
final Location loc = entity.getLocation();
|
||||
if (BukkitUtil.getLocation(loc).isPlotRoad()) {
|
||||
final Entity passenger = entity.getPassenger();
|
||||
if (!(passenger instanceof Player)) {
|
||||
if (entity.getMetadata("keep").isEmpty()) {
|
||||
iter.remove();
|
||||
entity.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (final Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 20);
|
||||
}
|
||||
|
||||
@Override
|
||||
final public ChunkGenerator getDefaultWorldGenerator(final String world, final String id) {
|
||||
WorldEvents.lastWorld = world;
|
||||
final HybridGen result = new HybridGen();
|
||||
if (!PS.get().setupPlotWorld(world, id, result)) {
|
||||
return null;
|
||||
}
|
||||
TaskManager.runTaskLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if ((WorldEvents.lastWorld != null) && WorldEvents.lastWorld.equals(world)) {
|
||||
WorldEvents.lastWorld = null;
|
||||
}
|
||||
}
|
||||
}, 20);
|
||||
return (ChunkGenerator) result.specify();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPlayerEvents() {
|
||||
getServer().getPluginManager().registerEvents(new PlayerEvents(), this);
|
||||
if (PS.get().checkVersion(getServerVersion(), 1, 8, 0)) {
|
||||
getServer().getPluginManager().registerEvents(new PlayerEvents_1_8(), this);
|
||||
}
|
||||
if (PS.get().checkVersion(getServerVersion(), 1, 8, 3)) {
|
||||
getServer().getPluginManager().registerEvents(new PlayerEvents_1_8_3(), this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerInventoryEvents() {
|
||||
// Part of PlayerEvents - can be moved if necessary
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPlotPlusEvents() {
|
||||
PlotPlusListener.startRunnable(this);
|
||||
getServer().getPluginManager().registerEvents(new PlotPlusListener(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerForceFieldEvents() {
|
||||
getServer().getPluginManager().registerEvents(new ForceFieldListener(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean initWorldEdit() {
|
||||
if (getServer().getPluginManager().getPlugin("WorldEdit") != null) {
|
||||
BukkitMain.worldEdit = (WorldEditPlugin) getServer().getPluginManager().getPlugin("WorldEdit");
|
||||
final String version = BukkitMain.worldEdit.getDescription().getVersion();
|
||||
if ((version != null) && version.startsWith("5.")) {
|
||||
log("&cThis version of WorldEdit does not support PlotSquared.");
|
||||
log("&cPlease use WorldEdit 6+ for masking support");
|
||||
log("&c - http://builds.enginehub.org/job/worldedit");
|
||||
} else {
|
||||
getServer().getPluginManager().registerEvents(new WEListener(), this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EconHandler getEconomyHandler() {
|
||||
try {
|
||||
final BukkitEconHandler econ = new BukkitEconHandler();
|
||||
if (econ.init()) {
|
||||
return econ;
|
||||
}
|
||||
} catch (final Throwable ignored) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotQueue initPlotQueue() {
|
||||
try {
|
||||
new SendChunk();
|
||||
MainUtil.canSendChunk = true;
|
||||
} catch (final Throwable e) {
|
||||
e.printStackTrace();
|
||||
MainUtil.canSendChunk = false;
|
||||
}
|
||||
if (PS.get().checkVersion(getServerVersion(), 1, 8, 0)) {
|
||||
try {
|
||||
return new FastQueue_1_8_3();
|
||||
} catch (NoSuchMethodException | RuntimeException e) {
|
||||
e.printStackTrace();
|
||||
try {
|
||||
return new FastQueue_1_8();
|
||||
} catch (NoSuchMethodException e2) {
|
||||
e2.printStackTrace();
|
||||
return new SlowQueue();
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
return new FastQueue_1_7();
|
||||
} catch (NoSuchMethodException e) {
|
||||
return new SlowQueue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldUtil initWorldUtil() {
|
||||
return new BukkitUtil();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean initPlotMeConverter() {
|
||||
TaskManager.runTaskLaterAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (new LikePlotMeConverter("PlotMe").run(new ClassicPlotMeConnector())) {
|
||||
return;
|
||||
}
|
||||
if (new LikePlotMeConverter("PlotMe").run(new PlotMeConnector_017())) {
|
||||
return;
|
||||
}
|
||||
if (new LikePlotMeConverter("AthionPlots").run(new ClassicPlotMeConnector())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}, 20);
|
||||
return (Bukkit.getPluginManager().getPlugin("PlotMe") != null) || (Bukkit.getPluginManager().getPlugin("AthionPlots") != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeneratorWrapper<?> getGenerator(final String world, final String name) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
final Plugin gen_plugin = Bukkit.getPluginManager().getPlugin(name);
|
||||
if ((gen_plugin != null) && gen_plugin.isEnabled()) {
|
||||
ChunkGenerator gen = gen_plugin.getDefaultWorldGenerator(world, "");
|
||||
if (gen instanceof GeneratorWrapper<?>) {
|
||||
return (GeneratorWrapper<?>) gen;
|
||||
}
|
||||
return new BukkitPlotGenerator(world, gen);
|
||||
} else {
|
||||
return new BukkitPlotGenerator(new HybridGen());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public HybridUtils initHybridUtils() {
|
||||
return new BukkitHybridUtils();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SetupUtils initSetupUtils() {
|
||||
return new BukkitSetupUtils();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUIDHandlerImplementation initUUIDHandler() {
|
||||
final boolean checkVersion = PS.get().checkVersion(getServerVersion(), 1, 7, 6);
|
||||
UUIDWrapper wrapper;
|
||||
if (Settings.OFFLINE_MODE) {
|
||||
if (Settings.UUID_LOWERCASE) {
|
||||
wrapper = (new LowerOfflineUUIDWrapper());
|
||||
} else {
|
||||
wrapper = (new OfflineUUIDWrapper());
|
||||
}
|
||||
Settings.OFFLINE_MODE = true;
|
||||
} else if (checkVersion) {
|
||||
wrapper = (new DefaultUUIDWrapper());
|
||||
Settings.OFFLINE_MODE = false;
|
||||
} else {
|
||||
if (Settings.UUID_LOWERCASE) {
|
||||
wrapper = (new LowerOfflineUUIDWrapper());
|
||||
} else {
|
||||
wrapper = (new OfflineUUIDWrapper());
|
||||
}
|
||||
Settings.OFFLINE_MODE = true;
|
||||
}
|
||||
if (!checkVersion) {
|
||||
log(C.PREFIX.s() + " &c[WARN] Titles are disabled - please update your version of Bukkit to support this feature.");
|
||||
Settings.TITLES = false;
|
||||
FlagManager.removeFlag(FlagManager.getFlag("titles"));
|
||||
} else {
|
||||
AbstractTitle.TITLE_CLASS = new DefaultTitle();
|
||||
if (wrapper instanceof DefaultUUIDWrapper || wrapper.getClass() == OfflineUUIDWrapper.class && !Bukkit.getOnlineMode()) {
|
||||
Settings.TWIN_MODE_UUID = true;
|
||||
}
|
||||
}
|
||||
if (Settings.OFFLINE_MODE) {
|
||||
log(C.PREFIX.s() + " &6PlotSquared is using Offline Mode UUIDs either because of user preference, or because you are using an old version of Bukkit");
|
||||
} else {
|
||||
log(C.PREFIX.s() + " &6PlotSquared is using online UUIDs");
|
||||
}
|
||||
return Settings.USE_SQLUUIDHANDLER ? new SQLUUIDHandler(wrapper) : new FileUUIDHandler(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkManager initChunkManager() {
|
||||
return new BukkitChunkManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventUtil initEventUtil() {
|
||||
return new BukkitEventUtil();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregister(final PlotPlayer player) {
|
||||
BukkitUtil.removePlayer(player.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerChunkProcessor() {
|
||||
getServer().getPluginManager().registerEvents(new ChunkListener(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerWorldEvents() {
|
||||
getServer().getPluginManager().registerEvents(new WorldEvents(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InventoryUtil initInventoryUtil() {
|
||||
return new BukkitInventoryUtil();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerName() {
|
||||
return Bukkit.getServerName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startMetrics() {
|
||||
try {
|
||||
final Metrics metrics = new Metrics(this);
|
||||
metrics.start();
|
||||
log(C.PREFIX.s() + "&6Metrics enabled.");
|
||||
} catch (IOException e) {
|
||||
log(C.PREFIX.s() + "&cFailed to load up metrics.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGenerator(final String worldname) {
|
||||
World world = BukkitUtil.getWorld(worldname);
|
||||
if (world == null) {
|
||||
// create world
|
||||
final ConfigurationSection worldConfig = PS.get().config.getConfigurationSection("worlds." + worldname);
|
||||
String manager = worldConfig.getString("generator.plugin");
|
||||
if (manager == null) {
|
||||
manager = "PlotSquared";
|
||||
}
|
||||
String generator = worldConfig.getString("generator.init");
|
||||
if (generator == null) {
|
||||
generator = manager;
|
||||
}
|
||||
|
||||
final int type = worldConfig.getInt("generator.type");
|
||||
final int terrain = worldConfig.getInt("generator.terrain");
|
||||
final SetupObject setup = new SetupObject();
|
||||
setup.plotManager = manager;
|
||||
setup.setupGenerator = generator;
|
||||
setup.type = type;
|
||||
setup.terrain = terrain;
|
||||
setup.step = new ConfigurationNode[0];
|
||||
setup.world = worldname;
|
||||
SetupUtils.manager.setupWorld(setup);
|
||||
} else {
|
||||
try {
|
||||
if (!PS.get().hasPlotArea(worldname)) {
|
||||
SetGenCB.setGenerator(BukkitUtil.getWorld(worldname));
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
log("Failed to reload world: " + world);
|
||||
Bukkit.getServer().unloadWorld(world, false);
|
||||
}
|
||||
}
|
||||
world = Bukkit.getWorld(worldname);
|
||||
final ChunkGenerator gen = world.getGenerator();
|
||||
if (gen instanceof BukkitPlotGenerator) {
|
||||
PS.get().loadWorld(worldname, (BukkitPlotGenerator) gen);
|
||||
} else if (gen != null) {
|
||||
PS.get().loadWorld(worldname, new BukkitPlotGenerator(worldname, gen));
|
||||
} else {
|
||||
if (PS.get().config.contains("worlds." + worldname)) {
|
||||
PS.get().loadWorld(worldname, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchematicHandler initSchematicHandler() {
|
||||
return new BukkitSchematicHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractTitle initTitleManager() {
|
||||
// Already initialized in UUID handler
|
||||
return AbstractTitle.TITLE_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotPlayer wrapPlayer(final Object obj) {
|
||||
if (obj instanceof Player) {
|
||||
return BukkitUtil.getPlayer((Player) obj);
|
||||
} else if (obj instanceof OfflinePlayer) {
|
||||
return BukkitUtil.getPlayer((OfflinePlayer) obj);
|
||||
} else if (obj instanceof String) {
|
||||
return UUIDHandler.getPlayer((String) obj);
|
||||
} else if (obj instanceof UUID) {
|
||||
return UUIDHandler.getPlayer((UUID) obj);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNMSPackage() {
|
||||
final Server server = Bukkit.getServer();
|
||||
final Class<?> bukkitServerClass = server.getClass();
|
||||
String[] pas = bukkitServerClass.getName().split("\\.");
|
||||
if (pas.length == 5) {
|
||||
return pas[3];
|
||||
}
|
||||
try {
|
||||
final Method getHandle = bukkitServerClass.getDeclaredMethod("getHandle");
|
||||
final Object handle = getHandle.invoke(server);
|
||||
final Class handleServerClass = handle.getClass();
|
||||
pas = handleServerClass.getName().split("\\.");
|
||||
if (pas.length == 5) {
|
||||
return pas[3];
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException | SecurityException | NoSuchMethodException | IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
PS.debug("Unknown NMS package: " + StringMan.getString(pas));
|
||||
return "1_8_R3";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatManager<?> initChatManager() {
|
||||
if (Settings.FANCY_CHAT) {
|
||||
return new BukkitChatManager();
|
||||
} else {
|
||||
return new BukkitPlainChatManager();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeneratorWrapper<?> wrapPlotGenerator(IndependentPlotGenerator generator) {
|
||||
return new BukkitPlotGenerator(generator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getPluginIds() {
|
||||
ArrayList<String> names = new ArrayList<>();
|
||||
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
|
||||
names.add(plugin.getName() + ";" + plugin.getDescription().getVersion() + ":" + plugin.isEnabled());
|
||||
}
|
||||
return names;
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
package com.plotsquared.bukkit.chat;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
|
||||
/**
|
||||
* Represents a wrapper around an array class of an arbitrary reference type,
|
||||
* which properly implements "value" hash code and equality functions.
|
||||
* <p>
|
||||
* This class is intended for use as a key to a map.
|
||||
* </p>
|
||||
* @author Glen Husman
|
||||
* @param <E> The type of elements in the array.
|
||||
* @see Arrays
|
||||
*/
|
||||
public final class ArrayWrapper<E> {
|
||||
|
||||
/**
|
||||
* Creates an array wrapper with some elements.
|
||||
* @param elements The elements of the array.
|
||||
*/
|
||||
public ArrayWrapper(final E... elements) {
|
||||
setArray(elements);
|
||||
}
|
||||
|
||||
private E[] _array;
|
||||
|
||||
/**
|
||||
* Retrieves a reference to the wrapped array instance.
|
||||
* @return The array wrapped by this instance.
|
||||
*/
|
||||
public E[] getArray() {
|
||||
return _array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this wrapper to wrap a new array instance.
|
||||
* @param array The new wrapped array.
|
||||
*/
|
||||
public void setArray(final E[] array) {
|
||||
Validate.notNull(array, "The array must not be null.");
|
||||
_array = array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if this object has a value equivalent to another object.
|
||||
* @see Arrays#equals(Object[], Object[])
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public boolean equals(final Object other) {
|
||||
if (!(other instanceof ArrayWrapper)) {
|
||||
return false;
|
||||
}
|
||||
return Arrays.equals(_array, ((ArrayWrapper) other)._array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hash code represented by this objects value.
|
||||
* @see Arrays#hashCode(Object[])
|
||||
* @return This object's hash code.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(_array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an iterable element collection to an array of elements.
|
||||
* The iteration order of the specified object will be used as the array element order.
|
||||
* @param list The iterable of objects which will be converted to an array.
|
||||
* @param c The type of the elements of the array.
|
||||
* @return An array of elements in the specified iterable.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T[] toArray(final Iterable<? extends T> list, final Class<T> c) {
|
||||
int size = -1;
|
||||
if (list instanceof Collection<?>) {
|
||||
@SuppressWarnings("rawtypes")
|
||||
final Collection coll = (Collection) list;
|
||||
size = coll.size();
|
||||
}
|
||||
|
||||
if (size < 0) {
|
||||
size = 0;
|
||||
// Ugly hack: Count it ourselves
|
||||
for (@SuppressWarnings("unused")
|
||||
final T element : list) {
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
final T[] result = (T[]) Array.newInstance(c, size);
|
||||
int i = 0;
|
||||
for (final T element : list) { // Assumes iteration order is consistent
|
||||
result[i++] = element; // Assign array element at index THEN increment counter
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1,847 @@
|
||||
package com.plotsquared.bukkit.chat;
|
||||
|
||||
import static com.plotsquared.bukkit.chat.TextualComponent.rawText;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.intellectualcrafters.configuration.serialization.ConfigurationSerializable;
|
||||
import com.intellectualcrafters.configuration.serialization.ConfigurationSerialization;
|
||||
import org.bukkit.Achievement;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.Statistic.Type;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Represents a formattable message. Such messages can use elements such as colors, formatting codes, hover and click data, and other features provided by the vanilla Minecraft <a href="http://minecraft.gamepedia.com/Tellraw#Raw_JSON_Text">JSON message formatter</a>.
|
||||
* This class allows plugins to emulate the functionality of the vanilla Minecraft <a href="http://minecraft.gamepedia.com/Commands#tellraw">tellraw command</a>.
|
||||
* <p>
|
||||
* This class follows the builder pattern, allowing for method chaining.
|
||||
* It is set up such that invocations of property-setting methods will affect the current editing component,
|
||||
* and a call to {@link #then(String)} or {@link #text(TextualComponent)} will append a new editing component to the end of the message,
|
||||
* optionally initializing it with text. Further property-setting method calls will affect that editing component.
|
||||
* </p>
|
||||
*/
|
||||
public class FancyMessage implements JsonRepresentedObject, Cloneable, Iterable<MessagePart>, ConfigurationSerializable {
|
||||
|
||||
static {
|
||||
ConfigurationSerialization.registerClass(FancyMessage.class);
|
||||
}
|
||||
|
||||
private List<MessagePart> messageParts;
|
||||
private String jsonString;
|
||||
private boolean dirty;
|
||||
|
||||
private static Constructor<?> nmsPacketPlayOutChatConstructor;
|
||||
|
||||
@Override
|
||||
public FancyMessage clone() throws CloneNotSupportedException {
|
||||
final FancyMessage instance = (FancyMessage) super.clone();
|
||||
instance.messageParts = new ArrayList<>(messageParts.size());
|
||||
for (int i = 0; i < messageParts.size(); i++) {
|
||||
instance.messageParts.add(i, messageParts.get(i).clone());
|
||||
}
|
||||
instance.dirty = false;
|
||||
instance.jsonString = null;
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JSON message with text.
|
||||
* @param firstPartText The existing text in the message.
|
||||
*/
|
||||
public FancyMessage(final String firstPartText) {
|
||||
this(rawText(firstPartText));
|
||||
}
|
||||
|
||||
public FancyMessage(final TextualComponent firstPartText) {
|
||||
messageParts = new ArrayList<>();
|
||||
messageParts.add(new MessagePart(firstPartText));
|
||||
jsonString = null;
|
||||
dirty = false;
|
||||
|
||||
if (nmsPacketPlayOutChatConstructor == null) {
|
||||
try {
|
||||
nmsPacketPlayOutChatConstructor = Reflection.getNMSClass("PacketPlayOutChat").getDeclaredConstructor(Reflection.getNMSClass("IChatBaseComponent"));
|
||||
nmsPacketPlayOutChatConstructor.setAccessible(true);
|
||||
} catch (final NoSuchMethodException e) {
|
||||
Bukkit.getLogger().log(Level.SEVERE, "Could not find Minecraft method or constructor.", e);
|
||||
} catch (final SecurityException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Could not access constructor.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JSON message without text.
|
||||
*/
|
||||
public FancyMessage() {
|
||||
this((TextualComponent) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the text of the current editing component to a value.
|
||||
* @param text The new text of the current editing component.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage text(final String text) {
|
||||
final MessagePart latest = latest();
|
||||
latest.text = rawText(text);
|
||||
dirty = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the text of the current editing component to a value.
|
||||
* @param text The new text of the current editing component.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage text(final TextualComponent text) {
|
||||
final MessagePart latest = latest();
|
||||
latest.text = text;
|
||||
dirty = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color of the current editing component to a value.
|
||||
* @param color The new color of the current editing component.
|
||||
* @return This builder instance.
|
||||
* @exception IllegalArgumentException If the specified {@code ChatColor} enumeration value is not a color (but a format value).
|
||||
*/
|
||||
public FancyMessage color(final ChatColor color) {
|
||||
latest().color = color;
|
||||
dirty = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stylization of the current editing component.
|
||||
* @param styles The array of styles to apply to the editing component.
|
||||
* @return This builder instance.
|
||||
* @exception IllegalArgumentException If any of the enumeration values in the array do not represent formatters.
|
||||
*/
|
||||
public FancyMessage style(final ChatColor... styles) {
|
||||
for (final ChatColor style : styles) {
|
||||
if (!style.isFormat()) {
|
||||
throw new IllegalArgumentException(style.name() + " is not a style");
|
||||
}
|
||||
}
|
||||
latest().styles.addAll(Arrays.asList(styles));
|
||||
dirty = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to instruct the client to open a file on the client side filesystem when the currently edited part of the {@code FancyMessage} is clicked.
|
||||
* @param path The path of the file on the client filesystem.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage file(final String path) {
|
||||
onClick("open_file", path);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to instruct the client to open a webpage in the client's web browser when the currently edited part of the {@code FancyMessage} is clicked.
|
||||
* @param url The URL of the page to open when the link is clicked.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage link(final String url) {
|
||||
onClick("open_url", url);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to instruct the client to replace the chat input box content with the specified string when the currently edited part of the {@code FancyMessage} is clicked.
|
||||
* The client will not immediately send the command to the server to be executed unless the client player submits the command/chat message, usually with the enter key.
|
||||
* @param command The text to display in the chat bar of the client.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage suggest(final String command) {
|
||||
onClick("suggest_command", command);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to instruct the client to append the chat input box content with the specified string when the currently edited part of the {@code FancyMessage} is SHIFT-CLICKED.
|
||||
* The client will not immediately send the command to the server to be executed unless the client player submits the command/chat message, usually with the enter key.
|
||||
* @param command The text to append to the chat bar of the client.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage insert(final String command) {
|
||||
latest().insertionData = command;
|
||||
dirty = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to instruct the client to send the specified string to the server as a chat message when the currently edited part of the {@code FancyMessage} is clicked.
|
||||
* The client <b>will</b> immediately send the command to the server to be executed when the editing component is clicked.
|
||||
* @param command The text to display in the chat bar of the client.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage command(final String command) {
|
||||
onClick("run_command", command);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to display information about an achievement when the client hovers over the text.
|
||||
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
|
||||
* @param name The name of the achievement to display, excluding the "achievement." prefix.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage achievementTooltip(final String name) {
|
||||
onHover("show_achievement", new JsonString("achievement." + name));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to display information about an achievement when the client hovers over the text.
|
||||
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
|
||||
* @param which The achievement to display.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage achievementTooltip(final Achievement which) {
|
||||
try {
|
||||
final Object achievement = Reflection.getMethod(Reflection.getOBCClass("CraftStatistic"), "getNMSAchievement", Achievement.class).invoke(null, which);
|
||||
return achievementTooltip((String) Reflection.getField(Reflection.getNMSClass("Achievement"), "name").get(achievement));
|
||||
} catch (final IllegalAccessException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
|
||||
return this;
|
||||
} catch (final IllegalArgumentException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
|
||||
return this;
|
||||
} catch (final InvocationTargetException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "A error has occurred during invoking of method.", e);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to display information about a parameterless statistic when the client hovers over the text.
|
||||
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
|
||||
* @param which The statistic to display.
|
||||
* @return This builder instance.
|
||||
* @exception IllegalArgumentException If the statistic requires a parameter which was not supplied.
|
||||
*/
|
||||
public FancyMessage statisticTooltip(final Statistic which) {
|
||||
final Type type = which.getType();
|
||||
if (type != Type.UNTYPED) {
|
||||
throw new IllegalArgumentException("That statistic requires an additional " + type + " parameter!");
|
||||
}
|
||||
try {
|
||||
final Object statistic = Reflection.getMethod(Reflection.getOBCClass("CraftStatistic"), "getNMSStatistic", Statistic.class).invoke(null, which);
|
||||
return achievementTooltip((String) Reflection.getField(Reflection.getNMSClass("Statistic"), "name").get(statistic));
|
||||
} catch (final IllegalAccessException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
|
||||
return this;
|
||||
} catch (final IllegalArgumentException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
|
||||
return this;
|
||||
} catch (final InvocationTargetException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "A error has occurred during invoking of method.", e);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to display information about a statistic parameter with a material when the client hovers over the text.
|
||||
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
|
||||
* @param which The statistic to display.
|
||||
* @param item The sole material parameter to the statistic.
|
||||
* @return This builder instance.
|
||||
* @exception IllegalArgumentException If the statistic requires a parameter which was not supplied, or was supplied a parameter that was not required.
|
||||
*/
|
||||
public FancyMessage statisticTooltip(final Statistic which, final Material item) {
|
||||
final Type type = which.getType();
|
||||
if (type == Type.UNTYPED) {
|
||||
throw new IllegalArgumentException("That statistic needs no additional parameter!");
|
||||
}
|
||||
if (((type == Type.BLOCK) && item.isBlock()) || (type == Type.ENTITY)) {
|
||||
throw new IllegalArgumentException("Wrong parameter type for that statistic - needs " + type + "!");
|
||||
}
|
||||
try {
|
||||
final Object statistic = Reflection.getMethod(Reflection.getOBCClass("CraftStatistic"), "getMaterialStatistic", Statistic.class, Material.class).invoke(null, which, item);
|
||||
return achievementTooltip((String) Reflection.getField(Reflection.getNMSClass("Statistic"), "name").get(statistic));
|
||||
} catch (final IllegalAccessException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
|
||||
return this;
|
||||
} catch (final IllegalArgumentException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
|
||||
return this;
|
||||
} catch (final InvocationTargetException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "A error has occurred during invoking of method.", e);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to display information about a statistic parameter with an entity type when the client hovers over the text.
|
||||
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
|
||||
* @param which The statistic to display.
|
||||
* @param entity The sole entity type parameter to the statistic.
|
||||
* @return This builder instance.
|
||||
* @exception IllegalArgumentException If the statistic requires a parameter which was not supplied, or was supplied a parameter that was not required.
|
||||
*/
|
||||
public FancyMessage statisticTooltip(final Statistic which, final EntityType entity) {
|
||||
final Type type = which.getType();
|
||||
if (type == Type.UNTYPED) {
|
||||
throw new IllegalArgumentException("That statistic needs no additional parameter!");
|
||||
}
|
||||
if (type != Type.ENTITY) {
|
||||
throw new IllegalArgumentException("Wrong parameter type for that statistic - needs " + type + "!");
|
||||
}
|
||||
try {
|
||||
final Object statistic = Reflection.getMethod(Reflection.getOBCClass("CraftStatistic"), "getEntityStatistic", Statistic.class, EntityType.class).invoke(null, which, entity);
|
||||
return achievementTooltip((String) Reflection.getField(Reflection.getNMSClass("Statistic"), "name").get(statistic));
|
||||
} catch (final IllegalAccessException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
|
||||
return this;
|
||||
} catch (final IllegalArgumentException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
|
||||
return this;
|
||||
} catch (final InvocationTargetException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "A error has occurred during invoking of method.", e);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to display information about an item when the client hovers over the text.
|
||||
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
|
||||
* @param itemJSON A string representing the JSON-serialized NBT data tag of an {@link ItemStack}.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage itemTooltip(final String itemJSON) {
|
||||
onHover("show_item", new JsonString(itemJSON)); // Seems a bit hacky, considering we have a JSON object as a parameter
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to display information about an item when the client hovers over the text.
|
||||
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
|
||||
* @param itemStack The stack for which to display information.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage itemTooltip(final ItemStack itemStack) {
|
||||
try {
|
||||
final Object nmsItem = Reflection.getMethod(Reflection.getOBCClass("inventory.CraftItemStack"), "asNMSCopy", ItemStack.class).invoke(null, itemStack);
|
||||
return itemTooltip(Reflection.getMethod(Reflection.getNMSClass("ItemStack"), "save", Reflection.getNMSClass("NBTTagCompound"))
|
||||
.invoke(nmsItem, Reflection.getNMSClass("NBTTagCompound").newInstance()).toString());
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to display raw text when the client hovers over the text.
|
||||
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
|
||||
* @param text The text, which supports newlines, which will be displayed to the client upon hovering.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage tooltip(final String text) {
|
||||
onHover("show_text", new JsonString(text));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to display raw text when the client hovers over the text.
|
||||
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
|
||||
* @param lines The lines of text which will be displayed to the client upon hovering. The iteration order of this object will be the order in which the lines of the tooltip are created.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage tooltip(final Iterable<String> lines) {
|
||||
tooltip(ArrayWrapper.toArray(lines, String.class));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to display raw text when the client hovers over the text.
|
||||
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
|
||||
* @param lines The lines of text which will be displayed to the client upon hovering.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage tooltip(final String... lines) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
builder.append(lines[i]);
|
||||
if (i != (lines.length - 1)) {
|
||||
builder.append('\n');
|
||||
}
|
||||
}
|
||||
tooltip(builder.toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to display formatted text when the client hovers over the text.
|
||||
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
|
||||
* @param text The formatted text which will be displayed to the client upon hovering.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage formattedTooltip(final FancyMessage text) {
|
||||
for (final MessagePart component : text.messageParts) {
|
||||
if ((component.clickActionData != null) && (component.clickActionName != null)) {
|
||||
throw new IllegalArgumentException("The tooltip text cannot have click data.");
|
||||
} else if ((component.hoverActionData != null) && (component.hoverActionName != null)) {
|
||||
throw new IllegalArgumentException("The tooltip text cannot have a tooltip.");
|
||||
}
|
||||
}
|
||||
onHover("show_text", text);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to display the specified lines of formatted text when the client hovers over the text.
|
||||
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
|
||||
* @param lines The lines of formatted text which will be displayed to the client upon hovering.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage formattedTooltip(final FancyMessage... lines) {
|
||||
if (lines.length < 1) {
|
||||
onHover(null, null); // Clear tooltip
|
||||
return this;
|
||||
}
|
||||
|
||||
final FancyMessage result = new FancyMessage();
|
||||
result.messageParts.clear(); // Remove the one existing text component that exists by default, which destabilizes the object
|
||||
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
try {
|
||||
for (final MessagePart component : lines[i]) {
|
||||
if ((component.clickActionData != null) && (component.clickActionName != null)) {
|
||||
throw new IllegalArgumentException("The tooltip text cannot have click data.");
|
||||
} else if ((component.hoverActionData != null) && (component.hoverActionName != null)) {
|
||||
throw new IllegalArgumentException("The tooltip text cannot have a tooltip.");
|
||||
}
|
||||
if (component.hasText()) {
|
||||
result.messageParts.add(component.clone());
|
||||
}
|
||||
}
|
||||
if (i != (lines.length - 1)) {
|
||||
result.messageParts.add(new MessagePart(rawText("\n")));
|
||||
}
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Failed to clone object", e);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
return formattedTooltip(result.messageParts.isEmpty() ? null : result); // Throws NPE if size is 0, intended
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behavior of the current editing component to display the specified lines of formatted text when the client hovers over the text.
|
||||
* <p>Tooltips do not inherit display characteristics, such as color and styles, from the message component on which they are applied.</p>
|
||||
* @param lines The lines of text which will be displayed to the client upon hovering. The iteration order of this object will be the order in which the lines of the tooltip are created.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage formattedTooltip(final Iterable<FancyMessage> lines) {
|
||||
return formattedTooltip(ArrayWrapper.toArray(lines, FancyMessage.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* If the text is a translatable key, and it has replaceable values, this function can be used to set the replacements that will be used in the message.
|
||||
* @param replacements The replacements, in order, that will be used in the language-specific message.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage translationReplacements(final String... replacements) {
|
||||
for (final String str : replacements) {
|
||||
latest().translationReplacements.add(new JsonString(str));
|
||||
}
|
||||
dirty = true;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
/**
|
||||
* If the text is a translatable key, and it has replaceable values, this function can be used to set the replacements that will be used in the message.
|
||||
* @param replacements The replacements, in order, that will be used in the language-specific message.
|
||||
* @return This builder instance.
|
||||
*//* ------------
|
||||
public FancyMessage translationReplacements(final Iterable<? extends CharSequence> replacements){
|
||||
for(CharSequence str : replacements){
|
||||
latest().translationReplacements.add(new JsonString(str));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* If the text is a translatable key, and it has replaceable values, this function can be used to set the replacements that will be used in the message.
|
||||
* @param replacements The replacements, in order, that will be used in the language-specific message.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage translationReplacements(final FancyMessage... replacements) {
|
||||
Collections.addAll(latest().translationReplacements, replacements);
|
||||
|
||||
dirty = true;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the text is a translatable key, and it has replaceable values, this function can be used to set the replacements that will be used in the message.
|
||||
* @param replacements The replacements, in order, that will be used in the language-specific message.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage translationReplacements(final Iterable<FancyMessage> replacements) {
|
||||
return translationReplacements(ArrayWrapper.toArray(replacements, FancyMessage.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate construction of the current editing component, and begin construction of a new message component.
|
||||
* After a successful call to this method, all setter methods will refer to a new message component, created as a result of the call to this method.
|
||||
* @param text The text which will populate the new message component.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage then(final String text) {
|
||||
return then(rawText(text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate construction of the current editing component, and begin construction of a new message component.
|
||||
* After a successful call to this method, all setter methods will refer to a new message component, created as a result of the call to this method.
|
||||
* @param text The text which will populate the new message component.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage then(final TextualComponent text) {
|
||||
if (!latest().hasText()) {
|
||||
throw new IllegalStateException("previous message part has no text");
|
||||
}
|
||||
messageParts.add(new MessagePart(text));
|
||||
dirty = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate construction of the current editing component, and begin construction of a new message component.
|
||||
* After a successful call to this method, all setter methods will refer to a new message component, created as a result of the call to this method.
|
||||
* @return This builder instance.
|
||||
*/
|
||||
public FancyMessage then() {
|
||||
if (!latest().hasText()) {
|
||||
throw new IllegalStateException("previous message part has no text");
|
||||
}
|
||||
messageParts.add(new MessagePart());
|
||||
dirty = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeJson(final JsonWriter writer) throws IOException {
|
||||
if (messageParts.size() == 1) {
|
||||
latest().writeJson(writer);
|
||||
} else {
|
||||
writer.beginObject().name("text").value("").name("extra").beginArray();
|
||||
for (final MessagePart part : this) {
|
||||
part.writeJson(writer);
|
||||
}
|
||||
writer.endArray().endObject();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize this fancy message, converting it into syntactically-valid JSON using a {@link JsonWriter}.
|
||||
* This JSON should be compatible with vanilla formatter commands such as {@code /tellraw}.
|
||||
* @return The JSON string representing this object.
|
||||
*/
|
||||
public String toJSONString() {
|
||||
if (!dirty && (jsonString != null)) {
|
||||
return jsonString;
|
||||
}
|
||||
final StringWriter string = new StringWriter();
|
||||
final JsonWriter json = new JsonWriter(string);
|
||||
try {
|
||||
writeJson(json);
|
||||
json.close();
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException("invalid message");
|
||||
}
|
||||
jsonString = string.toString();
|
||||
dirty = false;
|
||||
return jsonString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends this message to a player. The player will receive the fully-fledged formatted display of this message.
|
||||
* @param player The player who will receive the message.
|
||||
*/
|
||||
public void send(final Player player) {
|
||||
send(player, toJSONString());
|
||||
}
|
||||
|
||||
private void send(final CommandSender sender, final String jsonString) {
|
||||
if (!(sender instanceof Player)) {
|
||||
sender.sendMessage(toOldMessageFormat());
|
||||
return;
|
||||
}
|
||||
final Player player = (Player) sender;
|
||||
try {
|
||||
final Object handle = Reflection.getHandle(player);
|
||||
final Object connection = Reflection.getField(handle.getClass(), "playerConnection").get(handle);
|
||||
Reflection.getMethod(connection.getClass(), "sendPacket", Reflection.getNMSClass("Packet")).invoke(connection, createChatPacket(jsonString));
|
||||
} catch (final IllegalArgumentException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Argument could not be passed.", e);
|
||||
} catch (final IllegalAccessException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Could not access method.", e);
|
||||
} catch (final InstantiationException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Underlying class is abstract.", e);
|
||||
} catch (final InvocationTargetException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "A error has occurred during invoking of method.", e);
|
||||
} catch (final NoSuchMethodException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Could not find method.", e);
|
||||
} catch (final ClassNotFoundException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "Could not find class.", e);
|
||||
}
|
||||
}
|
||||
|
||||
// The ChatSerializer's instance of Gson
|
||||
private static Object nmsChatSerializerGsonInstance;
|
||||
private static Method fromJsonMethod;
|
||||
|
||||
private Object createChatPacket(final String json) throws IllegalArgumentException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException,
|
||||
ClassNotFoundException {
|
||||
if (nmsChatSerializerGsonInstance == null) {
|
||||
// Find the field and its value, completely bypassing obfuscation
|
||||
Class<?> chatSerializerClazz;
|
||||
|
||||
final String version = Reflection.getVersion();
|
||||
final double majorVersion = Double.parseDouble(version.replace('_', '.').substring(1, 4));
|
||||
final int lesserVersion = Integer.parseInt(version.substring(6, 7));
|
||||
|
||||
if ((majorVersion < 1.8) || ((majorVersion == 1.8) && (lesserVersion == 1))) {
|
||||
chatSerializerClazz = Reflection.getNMSClass("ChatSerializer");
|
||||
} else {
|
||||
chatSerializerClazz = Reflection.getNMSClass("IChatBaseComponent$ChatSerializer");
|
||||
}
|
||||
|
||||
if (chatSerializerClazz == null) {
|
||||
throw new ClassNotFoundException("Can't find the ChatSerializer class");
|
||||
}
|
||||
|
||||
for (final Field declaredField : chatSerializerClazz.getDeclaredFields()) {
|
||||
if (Modifier.isFinal(declaredField.getModifiers()) && Modifier.isStatic(declaredField.getModifiers()) && declaredField.getType().getName().endsWith("Gson")) {
|
||||
// We've found our field
|
||||
declaredField.setAccessible(true);
|
||||
nmsChatSerializerGsonInstance = declaredField.get(null);
|
||||
fromJsonMethod = nmsChatSerializerGsonInstance.getClass().getMethod("fromJson", String.class, Class.class);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Since the method is so simple, and all the obfuscated methods have the same name, it's easier to reimplement 'IChatBaseComponent a(String)'
|
||||
than to reflectively call it
|
||||
Of course, the implementation may change, but fuzzy matches might break with signature changes
|
||||
*/
|
||||
final Object serializedChatComponent = fromJsonMethod.invoke(nmsChatSerializerGsonInstance, json, Reflection.getNMSClass("IChatBaseComponent"));
|
||||
|
||||
return nmsPacketPlayOutChatConstructor.newInstance(serializedChatComponent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends this message to a command sender.
|
||||
* If the sender is a player, they will receive the fully-fledged formatted display of this message.
|
||||
* Otherwise, they will receive a version of this message with less formatting.
|
||||
* @param sender The command sender who will receive the message.
|
||||
* @see #toOldMessageFormat()
|
||||
*/
|
||||
public void send(final CommandSender sender) {
|
||||
send(sender, toJSONString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends this message to multiple command senders.
|
||||
* @param senders The command senders who will receive the message.
|
||||
* @see #send(CommandSender)
|
||||
*/
|
||||
public void send(final Iterable<? extends CommandSender> senders) {
|
||||
final String string = toJSONString();
|
||||
for (final CommandSender sender : senders) {
|
||||
send(sender, string);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this message to a human-readable string with limited formatting.
|
||||
* This method is used to send this message to clients without JSON formatting support.
|
||||
* <p>
|
||||
* Serialization of this message by using this message will include (in this order for each message part):
|
||||
* <ol>
|
||||
* <li>The color of each message part.</li>
|
||||
* <li>The applicable stylization for each message part.</li>
|
||||
* <li>The core text of the message part.</li>
|
||||
* </ol>
|
||||
* The primary omissions are tooltips and clickable actions. Consequently, this method should be used only as a last resort.
|
||||
* </p>
|
||||
* <p>
|
||||
* Color and formatting can be removed from the returned string by using {@link ChatColor#stripColor(String)}.</p>
|
||||
* @return A human-readable string representing limited formatting in addition to the core text of this message.
|
||||
*/
|
||||
public String toOldMessageFormat() {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
for (final MessagePart part : this) {
|
||||
result.append(part.color == null ? "" : part.color);
|
||||
for (final ChatColor formatSpecifier : part.styles) {
|
||||
result.append(formatSpecifier);
|
||||
}
|
||||
result.append(part.text);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private MessagePart latest() {
|
||||
return messageParts.get(messageParts.size() - 1);
|
||||
}
|
||||
|
||||
private void onClick(final String name, final String data) {
|
||||
final MessagePart latest = latest();
|
||||
latest.clickActionName = name;
|
||||
latest.clickActionData = data;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
private void onHover(final String name, final JsonRepresentedObject data) {
|
||||
final MessagePart latest = latest();
|
||||
latest.hoverActionName = name;
|
||||
latest.hoverActionData = data;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
// Doc copied from interface
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
final HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("messageParts", messageParts);
|
||||
// map.put("JSON", toJSONString());
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize a JSON-represented message from a mapping of key-value pairs.
|
||||
* This is called by the Bukkit serialization API.
|
||||
* It is not intended for direct public API consumption.
|
||||
* @param serialized The key-value mapping which represents a fancy message.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static FancyMessage deserialize(final Map<String, Object> serialized) {
|
||||
final FancyMessage msg = new FancyMessage();
|
||||
msg.messageParts = (List<MessagePart>) serialized.get("messageParts");
|
||||
msg.jsonString = serialized.containsKey("JSON") ? serialized.get("JSON").toString() : null;
|
||||
msg.dirty = !serialized.containsKey("JSON");
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* <b>Internally called method. Not for API consumption.</b>
|
||||
*/
|
||||
@Override
|
||||
public Iterator<MessagePart> iterator() {
|
||||
return messageParts.iterator();
|
||||
}
|
||||
|
||||
private static JsonParser _stringParser = new JsonParser();
|
||||
|
||||
/**
|
||||
* Deserialize a fancy message from its JSON representation. This JSON representation is of the format of
|
||||
* that returned by {@link #toJSONString()}, and is compatible with vanilla inputs.
|
||||
* @param json The JSON string which represents a fancy message.
|
||||
* @return A {@code FancyMessage} representing the parametrized JSON message.
|
||||
*/
|
||||
public static FancyMessage deserialize(final String json) {
|
||||
final JsonObject serialized = _stringParser.parse(json).getAsJsonObject();
|
||||
final JsonArray extra = serialized.getAsJsonArray("extra"); // Get the extra component
|
||||
final FancyMessage returnVal = new FancyMessage();
|
||||
returnVal.messageParts.clear();
|
||||
for (final JsonElement mPrt : extra) {
|
||||
final MessagePart component = new MessagePart();
|
||||
final JsonObject messagePart = mPrt.getAsJsonObject();
|
||||
for (final Map.Entry<String, JsonElement> entry : messagePart.entrySet()) {
|
||||
// Deserialize text
|
||||
if (TextualComponent.isTextKey(entry.getKey())) {
|
||||
// The map mimics the YAML serialization, which has a "key" field and one or more "value" fields
|
||||
final Map<String, Object> serializedMapForm = new HashMap<>(); // Must be object due to Bukkit serializer API compliance
|
||||
serializedMapForm.put("key", entry.getKey());
|
||||
if (entry.getValue().isJsonPrimitive()) {
|
||||
// Assume string
|
||||
serializedMapForm.put("value", entry.getValue().getAsString());
|
||||
} else {
|
||||
// Composite object, but we assume each element is a string
|
||||
for (final Map.Entry<String, JsonElement> compositeNestedElement : entry.getValue().getAsJsonObject().entrySet()) {
|
||||
serializedMapForm.put("value." + compositeNestedElement.getKey(), compositeNestedElement.getValue().getAsString());
|
||||
}
|
||||
}
|
||||
component.text = TextualComponent.deserialize(serializedMapForm);
|
||||
} else if (MessagePart.stylesToNames.inverse().containsKey(entry.getKey())) {
|
||||
if (entry.getValue().getAsBoolean()) {
|
||||
component.styles.add(MessagePart.stylesToNames.inverse().get(entry.getKey()));
|
||||
}
|
||||
} else if (entry.getKey().equals("color")) {
|
||||
component.color = ChatColor.valueOf(entry.getValue().getAsString().toUpperCase());
|
||||
} else if (entry.getKey().equals("clickEvent")) {
|
||||
final JsonObject object = entry.getValue().getAsJsonObject();
|
||||
component.clickActionName = object.get("action").getAsString();
|
||||
component.clickActionData = object.get("value").getAsString();
|
||||
} else if (entry.getKey().equals("hoverEvent")) {
|
||||
final JsonObject object = entry.getValue().getAsJsonObject();
|
||||
component.hoverActionName = object.get("action").getAsString();
|
||||
if (object.get("value").isJsonPrimitive()) {
|
||||
// Assume string
|
||||
component.hoverActionData = new JsonString(object.get("value").getAsString());
|
||||
} else {
|
||||
// Assume composite type
|
||||
// The only composite type we currently store is another FancyMessage
|
||||
// Therefore, recursion time!
|
||||
component.hoverActionData = deserialize(object.get("value").toString() /* This should properly serialize the JSON object as a JSON string */);
|
||||
}
|
||||
} else if (entry.getKey().equals("insertion")) {
|
||||
component.insertionData = entry.getValue().getAsString();
|
||||
} else if (entry.getKey().equals("with")) {
|
||||
for (final JsonElement object : entry.getValue().getAsJsonArray()) {
|
||||
if (object.isJsonPrimitive()) {
|
||||
component.translationReplacements.add(new JsonString(object.getAsString()));
|
||||
} else {
|
||||
// Only composite type stored in this array is - again - FancyMessages
|
||||
// Recurse within this function to parse this as a translation replacement
|
||||
component.translationReplacements.add(deserialize(object.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
returnVal.messageParts.add(component);
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.plotsquared.bukkit.chat;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
|
||||
/**
|
||||
* Represents an object that can be serialized to a JSON writer instance.
|
||||
*/
|
||||
interface JsonRepresentedObject {
|
||||
|
||||
/**
|
||||
* Writes the JSON representation of this object to the specified writer.
|
||||
* @param writer The JSON writer which will receive the object.
|
||||
* @throws IOException If an error occurs writing to the stream.
|
||||
*/
|
||||
void writeJson(final JsonWriter writer) throws IOException;
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package com.plotsquared.bukkit.chat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.intellectualcrafters.configuration.serialization.ConfigurationSerializable;
|
||||
|
||||
/**
|
||||
* Represents a JSON string value.
|
||||
* Writes by this object will not write name values nor begin/end objects in the JSON stream.
|
||||
* All writes merely write the represented string value.
|
||||
*/
|
||||
final class JsonString implements JsonRepresentedObject, ConfigurationSerializable {
|
||||
|
||||
private final String _value;
|
||||
|
||||
public JsonString(final CharSequence value) {
|
||||
_value = value == null ? null : value.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeJson(final JsonWriter writer) throws IOException {
|
||||
writer.value(getValue());
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return _value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
final HashMap<String, Object> theSingleValue = new HashMap<String, Object>();
|
||||
theSingleValue.put("stringValue", _value);
|
||||
return theSingleValue;
|
||||
}
|
||||
|
||||
public static JsonString deserialize(final Map<String, Object> map) {
|
||||
return new JsonString(map.get("stringValue").toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return _value;
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
package com.plotsquared.bukkit.chat;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.intellectualcrafters.configuration.serialization.ConfigurationSerializable;
|
||||
import com.intellectualcrafters.configuration.serialization.ConfigurationSerialization;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Internal class: Represents a component of a JSON-serializable {@link FancyMessage}.
|
||||
*/
|
||||
final class MessagePart implements JsonRepresentedObject, ConfigurationSerializable, Cloneable {
|
||||
|
||||
static final BiMap<ChatColor, String> stylesToNames;
|
||||
|
||||
static {
|
||||
final ImmutableBiMap.Builder<ChatColor, String> builder = ImmutableBiMap.builder();
|
||||
for (final ChatColor style : ChatColor.values()) {
|
||||
if (!style.isFormat()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String styleName;
|
||||
switch (style) {
|
||||
case MAGIC:
|
||||
styleName = "obfuscated";
|
||||
break;
|
||||
case UNDERLINE:
|
||||
styleName = "underlined";
|
||||
break;
|
||||
default:
|
||||
styleName = style.name().toLowerCase();
|
||||
break;
|
||||
}
|
||||
|
||||
builder.put(style, styleName);
|
||||
}
|
||||
stylesToNames = builder.build();
|
||||
}
|
||||
|
||||
static {
|
||||
ConfigurationSerialization.registerClass(MessagePart.class);
|
||||
}
|
||||
|
||||
ChatColor color = ChatColor.WHITE;
|
||||
ArrayList<ChatColor> styles = new ArrayList<ChatColor>();
|
||||
String clickActionName = null, clickActionData = null, hoverActionName = null;
|
||||
JsonRepresentedObject hoverActionData = null;
|
||||
TextualComponent text = null;
|
||||
String insertionData = null;
|
||||
ArrayList<JsonRepresentedObject> translationReplacements = new ArrayList<JsonRepresentedObject>();
|
||||
|
||||
MessagePart(final TextualComponent text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
MessagePart() {
|
||||
text = null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static MessagePart deserialize(final Map<String, Object> serialized) {
|
||||
final MessagePart part = new MessagePart((TextualComponent) serialized.get("text"));
|
||||
part.styles = (ArrayList<ChatColor>) serialized.get("styles");
|
||||
part.color = ChatColor.getByChar(serialized.get("color").toString());
|
||||
part.hoverActionName = (String) serialized.get("hoverActionName");
|
||||
part.hoverActionData = (JsonRepresentedObject) serialized.get("hoverActionData");
|
||||
part.clickActionName = (String) serialized.get("clickActionName");
|
||||
part.clickActionData = (String) serialized.get("clickActionData");
|
||||
part.insertionData = (String) serialized.get("insertion");
|
||||
part.translationReplacements = (ArrayList<JsonRepresentedObject>) serialized.get("translationReplacements");
|
||||
return part;
|
||||
}
|
||||
|
||||
boolean hasText() {
|
||||
return text != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public MessagePart clone() throws CloneNotSupportedException {
|
||||
final MessagePart obj = (MessagePart) super.clone();
|
||||
obj.styles = (ArrayList<ChatColor>) styles.clone();
|
||||
if (hoverActionData instanceof JsonString) {
|
||||
obj.hoverActionData = new JsonString(((JsonString) hoverActionData).getValue());
|
||||
} else if (hoverActionData instanceof FancyMessage) {
|
||||
obj.hoverActionData = ((FancyMessage) hoverActionData).clone();
|
||||
}
|
||||
obj.translationReplacements = (ArrayList<JsonRepresentedObject>) translationReplacements.clone();
|
||||
return obj;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeJson(final JsonWriter json) {
|
||||
try {
|
||||
json.beginObject();
|
||||
text.writeJson(json);
|
||||
json.name("color").value(color.name().toLowerCase());
|
||||
for (final ChatColor style : styles) {
|
||||
json.name(stylesToNames.get(style)).value(true);
|
||||
}
|
||||
if ((clickActionName != null) && (clickActionData != null)) {
|
||||
json.name("clickEvent").beginObject().name("action").value(clickActionName).name("value").value(clickActionData).endObject();
|
||||
}
|
||||
if ((hoverActionName != null) && (hoverActionData != null)) {
|
||||
json.name("hoverEvent").beginObject().name("action").value(hoverActionName).name("value");
|
||||
hoverActionData.writeJson(json);
|
||||
json.endObject();
|
||||
}
|
||||
if (insertionData != null) {
|
||||
json.name("insertion").value(insertionData);
|
||||
}
|
||||
if ((!translationReplacements.isEmpty()) && (text != null) && TextualComponent.isTranslatableText(text)) {
|
||||
json.name("with").beginArray();
|
||||
for (final JsonRepresentedObject obj : translationReplacements) {
|
||||
obj.writeJson(json);
|
||||
}
|
||||
json.endArray();
|
||||
}
|
||||
json.endObject();
|
||||
} catch (final IOException e) {
|
||||
Bukkit.getLogger().log(Level.WARNING, "A problem occurred during writing of JSON string", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
final HashMap<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("text", text);
|
||||
map.put("styles", styles);
|
||||
map.put("color", color.getChar());
|
||||
map.put("hoverActionName", hoverActionName);
|
||||
map.put("hoverActionData", hoverActionData);
|
||||
map.put("clickActionName", clickActionName);
|
||||
map.put("clickActionData", clickActionData);
|
||||
map.put("insertion", insertionData);
|
||||
map.put("translationReplacements", translationReplacements);
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
227
Bukkit/src/main/java/com/plotsquared/bukkit/chat/Reflection.java
Normal file
227
Bukkit/src/main/java/com/plotsquared/bukkit/chat/Reflection.java
Normal file
@ -0,0 +1,227 @@
|
||||
package com.plotsquared.bukkit.chat;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A class containing static utility methods and caches which are intended as reflective conveniences.
|
||||
* Unless otherwise noted, upon failure methods will return {@code null}.
|
||||
*/
|
||||
public final class Reflection {
|
||||
|
||||
/**
|
||||
* Stores loaded classes from the {@code net.minecraft.server} package.
|
||||
*/
|
||||
private static final Map<String, Class<?>> _loadedNMSClasses = new HashMap<>();
|
||||
/**
|
||||
* Stores loaded classes from the {@code org.bukkit.craftbukkit} package (and subpackages).
|
||||
*/
|
||||
private static final Map<String, Class<?>> _loadedOBCClasses = new HashMap<>();
|
||||
private static final Map<Class<?>, Map<String, Field>> _loadedFields = new HashMap<>();
|
||||
/**
|
||||
* Contains loaded methods in a cache.
|
||||
* The map maps [types to maps of [method names to maps of [parameter types to method instances]]].
|
||||
*/
|
||||
private static final Map<Class<?>, Map<String, Map<ArrayWrapper<Class<?>>, Method>>> _loadedMethods = new HashMap<>();
|
||||
private static String _versionString;
|
||||
|
||||
private Reflection() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the version string from the package name of the CraftBukkit server implementation.
|
||||
* This is needed to bypass the JAR package name changing on each update.
|
||||
* @return The version string of the OBC and NMS packages, <em>including the trailing dot</em>.
|
||||
*/
|
||||
public synchronized static String getVersion() {
|
||||
if (_versionString == null) {
|
||||
if (Bukkit.getServer() == null) {
|
||||
// The server hasn't started, static initializer call?
|
||||
return null;
|
||||
}
|
||||
final String name = Bukkit.getServer().getClass().getPackage().getName();
|
||||
_versionString = name.substring(name.lastIndexOf('.') + 1) + ".";
|
||||
}
|
||||
|
||||
return _versionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Class} object representing a type contained within the {@code net.minecraft.server} versioned package.
|
||||
* The class instances returned by this method are cached, such that no lookup will be done twice (unless multiple threads are accessing this method simultaneously).
|
||||
* @param className The name of the class, excluding the package, within NMS.
|
||||
* @return The class instance representing the specified NMS class, or {@code null} if it could not be loaded.
|
||||
*/
|
||||
public synchronized static Class<?> getNMSClass(final String className) {
|
||||
if (_loadedNMSClasses.containsKey(className)) {
|
||||
return _loadedNMSClasses.get(className);
|
||||
}
|
||||
|
||||
final String fullName = "net.minecraft.server." + getVersion() + className;
|
||||
Class<?> clazz;
|
||||
try {
|
||||
clazz = Class.forName(fullName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
_loadedNMSClasses.put(className, null);
|
||||
return null;
|
||||
}
|
||||
_loadedNMSClasses.put(className, clazz);
|
||||
return clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Class} object representing a type contained within the {@code org.bukkit.craftbukkit} versioned package.
|
||||
* The class instances returned by this method are cached, such that no lookup will be done twice (unless multiple threads are accessing this
|
||||
* method simultaneously).
|
||||
* @param className The name of the class, excluding the package, within OBC. This name may contain a subpackage name, such as {@code inventory
|
||||
* .CraftItemStack}.
|
||||
* @return The class instance representing the specified OBC class, or {@code null} if it could not be loaded.
|
||||
*/
|
||||
public synchronized static Class<?> getOBCClass(final String className) {
|
||||
if (_loadedOBCClasses.containsKey(className)) {
|
||||
return _loadedOBCClasses.get(className);
|
||||
}
|
||||
|
||||
final String fullName = "org.bukkit.craftbukkit." + getVersion() + className;
|
||||
Class<?> clazz;
|
||||
try {
|
||||
clazz = Class.forName(fullName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
_loadedOBCClasses.put(className, null);
|
||||
return null;
|
||||
}
|
||||
_loadedOBCClasses.put(className, clazz);
|
||||
return clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to get the NMS handle of a CraftBukkit object.
|
||||
* <p>
|
||||
* The only match currently attempted by this method is a retrieval by using a parameterless {@code getHandle()} method implemented by the
|
||||
* runtime type of the specified object.
|
||||
* </p>
|
||||
* @param obj The object for which to retrieve an NMS handle.
|
||||
* @return The NMS handle of the specified object, or {@code null} if it could not be retrieved using {@code getHandle()}.
|
||||
*/
|
||||
public synchronized static Object getHandle(final Object obj) {
|
||||
try {
|
||||
return getMethod(obj.getClass(), "getHandle").invoke(obj);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a {@link Field} instance declared by the specified class with the specified name.
|
||||
* Java access modifiers are ignored during this retrieval. No guarantee is made as to whether the field
|
||||
* returned will be an instance or static field.
|
||||
* <p>
|
||||
* A global caching mechanism within this class is used to store fields. Combined with synchronization, this guarantees that
|
||||
* no field will be reflectively looked up twice.
|
||||
* </p>
|
||||
* <p>
|
||||
* If a field is deemed suitable for return,
|
||||
* {@link Field#setAccessible(boolean) setAccessible} will be invoked with an argument of {@code true} before it is returned.
|
||||
* This ensures that callers do not have to check or worry about Java access modifiers when dealing with the returned instance.
|
||||
* </p>
|
||||
* @param clazz The class which contains the field to retrieve.
|
||||
* @param name The declared name of the field in the class.
|
||||
* @return A field object with the specified name declared by the specified class.
|
||||
* @see Class#getDeclaredField(String)
|
||||
*/
|
||||
public synchronized static Field getField(final Class<?> clazz, final String name) {
|
||||
Map<String, Field> loaded;
|
||||
if (!_loadedFields.containsKey(clazz)) {
|
||||
loaded = new HashMap<>();
|
||||
_loadedFields.put(clazz, loaded);
|
||||
} else {
|
||||
loaded = _loadedFields.get(clazz);
|
||||
}
|
||||
if (loaded.containsKey(name)) {
|
||||
// If the field is loaded (or cached as not existing), return the relevant value, which might be null
|
||||
return loaded.get(name);
|
||||
}
|
||||
try {
|
||||
final Field field = clazz.getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
loaded.put(name, field);
|
||||
return field;
|
||||
} catch (NoSuchFieldException e) {
|
||||
// Error loading
|
||||
e.printStackTrace();
|
||||
// Cache field as not existing
|
||||
loaded.put(name, null);
|
||||
return null;
|
||||
} catch (SecurityException e) {
|
||||
// Error loading
|
||||
e.printStackTrace();
|
||||
// Cache field as not existing
|
||||
loaded.put(name, null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a {@link Method} instance declared by the specified class with the specified name and argument types.
|
||||
* Java access modifiers are ignored during this retrieval. No guarantee is made as to whether the field
|
||||
* returned will be an instance or static field.
|
||||
* <p>
|
||||
* A global caching mechanism within this class is used to store method. Combined with synchronization, this guarantees that
|
||||
* no method will be reflectively looked up twice.
|
||||
* </p>
|
||||
* <p>
|
||||
* If a method is deemed suitable for return, {@link Method#setAccessible(boolean) setAccessible} will be invoked with an argument of {@code true} before it is returned.
|
||||
* This ensures that callers do not have to check or worry about Java access modifiers when dealing with the returned instance.
|
||||
* </p>
|
||||
* <p>
|
||||
* This method does <em>not</em> search superclasses of the specified type for methods with the specified signature.
|
||||
* Callers wishing this behavior should use {@link Class#getDeclaredMethod(String, Class...)}.
|
||||
* @param clazz The class which contains the method to retrieve.
|
||||
* @param name The declared name of the method in the class.
|
||||
* @param args The formal argument types of the method.
|
||||
* @return A method object with the specified name declared by the specified class.
|
||||
*/
|
||||
public synchronized static Method getMethod(final Class<?> clazz, final String name, final Class<?>... args) {
|
||||
if (!_loadedMethods.containsKey(clazz)) {
|
||||
_loadedMethods.put(clazz, new HashMap<String, Map<ArrayWrapper<Class<?>>, Method>>());
|
||||
}
|
||||
|
||||
final Map<String, Map<ArrayWrapper<Class<?>>, Method>> loadedMethodNames = _loadedMethods.get(clazz);
|
||||
if (!loadedMethodNames.containsKey(name)) {
|
||||
loadedMethodNames.put(name, new HashMap<ArrayWrapper<Class<?>>, Method>());
|
||||
}
|
||||
|
||||
final Map<ArrayWrapper<Class<?>>, Method> loadedSignatures = loadedMethodNames.get(name);
|
||||
final ArrayWrapper<Class<?>> wrappedArg = new ArrayWrapper<>(args);
|
||||
if (loadedSignatures.containsKey(wrappedArg)) {
|
||||
return loadedSignatures.get(wrappedArg);
|
||||
}
|
||||
|
||||
for (final Method m : clazz.getMethods()) {
|
||||
if (m.getName().equals(name) && Arrays.equals(args, m.getParameterTypes())) {
|
||||
m.setAccessible(true);
|
||||
loadedSignatures.put(wrappedArg, m);
|
||||
return m;
|
||||
}
|
||||
}
|
||||
loadedSignatures.put(wrappedArg, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,293 @@
|
||||
package com.plotsquared.bukkit.chat;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.intellectualcrafters.configuration.serialization.ConfigurationSerializable;
|
||||
import com.intellectualcrafters.configuration.serialization.ConfigurationSerialization;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents a textual component of a message part.
|
||||
* This can be used to not only represent string literals in a JSON message,
|
||||
* but also to represent localized strings and other text values.
|
||||
* <p>Different instances of this class can be created with static constructor methods.</p>
|
||||
*/
|
||||
public abstract class TextualComponent implements Cloneable {
|
||||
|
||||
static {
|
||||
ConfigurationSerialization.registerClass(TextualComponent.ArbitraryTextTypeComponent.class);
|
||||
ConfigurationSerialization.registerClass(TextualComponent.ComplexTextTypeComponent.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReadableString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The JSON key used to represent text components of this type.
|
||||
*/
|
||||
public abstract String getKey();
|
||||
|
||||
/**
|
||||
* @return A readable String
|
||||
*/
|
||||
public abstract String getReadableString();
|
||||
|
||||
/**
|
||||
* Clones a textual component instance.
|
||||
* The returned object should not reference this textual component instance, but should maintain the same key and value.
|
||||
*/
|
||||
@Override
|
||||
public abstract TextualComponent clone() throws CloneNotSupportedException;
|
||||
|
||||
/**
|
||||
* Writes the text data represented by this textual component to the specified JSON writer object.
|
||||
* A new object within the writer is not started.
|
||||
* @param writer The object to which to write the JSON data.
|
||||
* @throws IOException If an error occurs while writing to the stream.
|
||||
*/
|
||||
public abstract void writeJson(final JsonWriter writer) throws IOException;
|
||||
|
||||
static TextualComponent deserialize(final Map<String, Object> map) {
|
||||
if (map.containsKey("key") && (map.size() == 2) && map.containsKey("value")) {
|
||||
// Arbitrary text component
|
||||
return ArbitraryTextTypeComponent.deserialize(map);
|
||||
} else if ((map.size() >= 2) && map.containsKey("key") && !map.containsKey("value") /* It contains keys that START WITH value */) {
|
||||
// Complex JSON object
|
||||
return ComplexTextTypeComponent.deserialize(map);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static boolean isTextKey(final String key) {
|
||||
return key.equals("translate") || key.equals("text") || key.equals("score") || key.equals("selector");
|
||||
}
|
||||
|
||||
static boolean isTranslatableText(final TextualComponent component) {
|
||||
return (component instanceof ComplexTextTypeComponent) && ((ComplexTextTypeComponent) component).getKey().equals("translate");
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal class used to represent all types of text components.
|
||||
* Exception validating done is on keys and values.
|
||||
*/
|
||||
private static final class ArbitraryTextTypeComponent extends TextualComponent implements ConfigurationSerializable {
|
||||
|
||||
public ArbitraryTextTypeComponent(final String key, final String value) {
|
||||
setKey(key);
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return _key;
|
||||
}
|
||||
|
||||
public void setKey(final String key) {
|
||||
Preconditions.checkArgument((key != null) && !key.isEmpty(), "The key must be specified.");
|
||||
_key = key;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return _value;
|
||||
}
|
||||
|
||||
public void setValue(final String value) {
|
||||
Preconditions.checkArgument(value != null, "The value must be specified.");
|
||||
_value = value;
|
||||
}
|
||||
|
||||
private String _key;
|
||||
private String _value;
|
||||
|
||||
@Override
|
||||
public TextualComponent clone() throws CloneNotSupportedException {
|
||||
// Since this is a private and final class, we can just reinstantiate this class instead of casting super.clone
|
||||
return new ArbitraryTextTypeComponent(getKey(), getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeJson(final JsonWriter writer) throws IOException {
|
||||
writer.name(getKey()).value(getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("serial")
|
||||
public Map<String, Object> serialize() {
|
||||
return new HashMap<String, Object>() {
|
||||
{
|
||||
put("key", getKey());
|
||||
put("value", getValue());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static ArbitraryTextTypeComponent deserialize(final Map<String, Object> map) {
|
||||
return new ArbitraryTextTypeComponent(map.get("key").toString(), map.get("value").toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReadableString() {
|
||||
return getValue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal class used to represent a text component with a nested JSON value.
|
||||
* Exception validating done is on keys and values.
|
||||
*/
|
||||
private static final class ComplexTextTypeComponent extends TextualComponent implements ConfigurationSerializable {
|
||||
|
||||
public ComplexTextTypeComponent(final String key, final Map<String, String> values) {
|
||||
setKey(key);
|
||||
setValue(values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return _key;
|
||||
}
|
||||
|
||||
public void setKey(final String key) {
|
||||
Preconditions.checkArgument((key != null) && !key.isEmpty(), "The key must be specified.");
|
||||
_key = key;
|
||||
}
|
||||
|
||||
public Map<String, String> getValue() {
|
||||
return _value;
|
||||
}
|
||||
|
||||
public void setValue(final Map<String, String> value) {
|
||||
Preconditions.checkArgument(value != null, "The value must be specified.");
|
||||
_value = value;
|
||||
}
|
||||
|
||||
private String _key;
|
||||
private Map<String, String> _value;
|
||||
|
||||
@Override
|
||||
public TextualComponent clone() throws CloneNotSupportedException {
|
||||
// Since this is a private and final class, we can just reinstantiate this class instead of casting super.clone
|
||||
return new ComplexTextTypeComponent(getKey(), getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeJson(final JsonWriter writer) throws IOException {
|
||||
writer.name(getKey());
|
||||
writer.beginObject();
|
||||
for (final Map.Entry<String, String> jsonPair : _value.entrySet()) {
|
||||
writer.name(jsonPair.getKey()).value(jsonPair.getValue());
|
||||
}
|
||||
writer.endObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("serial")
|
||||
public Map<String, Object> serialize() {
|
||||
return new java.util.HashMap<String, Object>() {
|
||||
{
|
||||
put("key", getKey());
|
||||
for (final Map.Entry<String, String> valEntry : getValue().entrySet()) {
|
||||
put("value." + valEntry.getKey(), valEntry.getValue());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static ComplexTextTypeComponent deserialize(final Map<String, Object> map) {
|
||||
String key = null;
|
||||
final Map<String, String> value = new HashMap<String, String>();
|
||||
for (final Map.Entry<String, Object> valEntry : map.entrySet()) {
|
||||
if (valEntry.getKey().equals("key")) {
|
||||
key = (String) valEntry.getValue();
|
||||
} else if (valEntry.getKey().startsWith("value.")) {
|
||||
value.put(valEntry.getKey().substring(6) /* Strips out the value prefix */, valEntry.getValue().toString());
|
||||
}
|
||||
}
|
||||
return new ComplexTextTypeComponent(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReadableString() {
|
||||
return getKey();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a textual component representing a string literal.
|
||||
* This is the default type of textual component when a single string literal is given to a method.
|
||||
* @param textValue The text which will be represented.
|
||||
* @return The text component representing the specified literal text.
|
||||
*/
|
||||
public static TextualComponent rawText(final String textValue) {
|
||||
return new ArbitraryTextTypeComponent("text", textValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a textual component representing a localized string.
|
||||
* The client will see this text component as their localized version of the specified string <em>key</em>, which can be overridden by a resource pack.
|
||||
* <p>
|
||||
* If the specified translation key is not present on the client resource pack, the translation key will be displayed as a string literal to the client.
|
||||
* </p>
|
||||
* @param translateKey The string key which maps to localized text.
|
||||
* @return The text component representing the specified localized text.
|
||||
*/
|
||||
public static TextualComponent localizedText(final String translateKey) {
|
||||
return new ArbitraryTextTypeComponent("translate", translateKey);
|
||||
}
|
||||
|
||||
private static void throwUnsupportedSnapshot() {
|
||||
throw new UnsupportedOperationException("This feature is only supported in snapshot releases.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a textual component representing a scoreboard value.
|
||||
* The client will see their own score for the specified objective as the text represented by this component.
|
||||
* <p>
|
||||
* <b>This method is currently guaranteed to throw an {@code UnsupportedOperationException} as it is only supported on snapshot clients.</b>
|
||||
* </p>
|
||||
* @param scoreboardObjective The name of the objective for which to display the score.
|
||||
* @return The text component representing the specified scoreboard score (for the viewing player), or {@code null} if an error occurs during JSON serialization.
|
||||
*/
|
||||
public static TextualComponent objectiveScore(final String scoreboardObjective) {
|
||||
return objectiveScore("*", scoreboardObjective);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a textual component representing a scoreboard value.
|
||||
* The client will see the score of the specified player for the specified objective as the text represented by this component.
|
||||
* <p>
|
||||
* <b>This method is currently guaranteed to throw an {@code UnsupportedOperationException} as it is only supported on snapshot clients.</b>
|
||||
* </p>
|
||||
* @param playerName The name of the player whos score will be shown. If this string represents the single-character sequence "*", the viewing player's score will be displayed.
|
||||
* Standard minecraft selectors (@a, @p, etc) are <em>not</em> supported.
|
||||
* @param scoreboardObjective The name of the objective for which to display the score.
|
||||
* @return The text component representing the specified scoreboard score for the specified player, or {@code null} if an error occurs during JSON serialization.
|
||||
*/
|
||||
public static TextualComponent objectiveScore(final String playerName, final String scoreboardObjective) {
|
||||
throwUnsupportedSnapshot(); // Remove this line when the feature is released to non-snapshot versions, in addition to updating ALL THE OVERLOADS documentation accordingly
|
||||
|
||||
return new ComplexTextTypeComponent("score", ImmutableMap.<String, String> builder().put("name", playerName).put("objective", scoreboardObjective).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a textual component representing a player name, retrievable by using a standard minecraft selector.
|
||||
* The client will see the players or entities captured by the specified selector as the text represented by this component.
|
||||
* <p>
|
||||
* <b>This method is currently guaranteed to throw an {@code UnsupportedOperationException} as it is only supported on snapshot clients.</b>
|
||||
* </p>
|
||||
* @param selector The minecraft player or entity selector which will capture the entities whose string representations will be displayed in the place of this text component.
|
||||
* @return The text component representing the name of the entities captured by the selector.
|
||||
*/
|
||||
public static TextualComponent selector(final String selector) {
|
||||
throwUnsupportedSnapshot(); // Remove this line when the feature is released to non-snapshot versions, in addition to updating ALL THE OVERLOADS documentation accordingly
|
||||
|
||||
return new ArbitraryTextTypeComponent("selector", selector);
|
||||
}
|
||||
}
|
@ -0,0 +1,332 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.commands;
|
||||
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.commands.CommandCategory;
|
||||
import com.intellectualcrafters.plot.commands.RequiredType;
|
||||
import com.intellectualcrafters.plot.commands.SubCommand;
|
||||
import com.intellectualcrafters.plot.config.C;
|
||||
import com.intellectualcrafters.plot.database.AbstractDB;
|
||||
import com.intellectualcrafters.plot.database.DBFunc;
|
||||
import com.intellectualcrafters.plot.object.OfflinePlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.StringWrapper;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
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.intellectualcrafters.plot.uuid.UUIDWrapper;
|
||||
import com.plotsquared.bukkit.uuid.DefaultUUIDWrapper;
|
||||
import com.plotsquared.bukkit.uuid.LowerOfflineUUIDWrapper;
|
||||
import com.plotsquared.bukkit.uuid.OfflineUUIDWrapper;
|
||||
import com.plotsquared.general.commands.Argument;
|
||||
import com.plotsquared.general.commands.CommandDeclaration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
@CommandDeclaration(
|
||||
command = "uuidconvert",
|
||||
permission = "plots.admin",
|
||||
description = "Debug UUID conversion",
|
||||
usage = "/plot uuidconvert <lower|offline|online>",
|
||||
requiredType = RequiredType.CONSOLE,
|
||||
category = CommandCategory.DEBUG)
|
||||
public class DebugUUID extends SubCommand {
|
||||
|
||||
public DebugUUID() {
|
||||
requiredArguments = new Argument[] { Argument.String };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(final PlotPlayer player, final String[] args) {
|
||||
final UUIDWrapper currentUUIDWrapper = UUIDHandler.getUUIDWrapper();
|
||||
final UUIDWrapper newWrapper;
|
||||
|
||||
switch (args[0].toLowerCase()) {
|
||||
case "lower":
|
||||
newWrapper = new LowerOfflineUUIDWrapper();
|
||||
break;
|
||||
case "offline":
|
||||
newWrapper = new OfflineUUIDWrapper();
|
||||
break;
|
||||
case "online":
|
||||
newWrapper = new DefaultUUIDWrapper();
|
||||
break;
|
||||
default:
|
||||
try {
|
||||
final Class<?> clazz = Class.forName(args[0]);
|
||||
newWrapper = (UUIDWrapper) clazz.newInstance();
|
||||
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot uuidconvert <lower|offline|online>");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (args.length != 2 || !"-o".equals(args[1])) {
|
||||
MainUtil.sendMessage(player, C.COMMAND_SYNTAX, "/plot uuidconvert " + args[0] + " - o");
|
||||
MainUtil.sendMessage(player, "&cBe aware of the following!");
|
||||
MainUtil.sendMessage(player, "&8 - &cUse the database command or another method to backup your plots beforehand");
|
||||
MainUtil.sendMessage(player, "&8 - &cIf the process is interrupted, all plots could be deleted");
|
||||
MainUtil.sendMessage(player, "&8 - &cIf an error occurs, all plots could be deleted");
|
||||
MainUtil.sendMessage(player, "&8 - &cPlot settings WILL be lost upon conversion");
|
||||
MainUtil.sendMessage(player, "&cTO REITERATE: BACK UP YOUR DATABASE BEFORE USING THIS!!!");
|
||||
MainUtil.sendMessage(player, "&7Retype the command with the override parameter when ready :)");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (currentUUIDWrapper.getClass().getCanonicalName().equals(newWrapper.getClass().getCanonicalName())) {
|
||||
MainUtil.sendMessage(player, "&cUUID mode already in use!");
|
||||
return false;
|
||||
}
|
||||
MainUtil.sendMessage(player, "&6Beginning UUID mode conversion");
|
||||
MainUtil.sendMessage(player, "&7 - Disconnecting players");
|
||||
for (Entry<String, PlotPlayer> entry : UUIDHandler.getPlayers().entrySet()) {
|
||||
entry.getValue().kick("PlotSquared UUID conversion has been initiated. You may reconnect when finished.");
|
||||
}
|
||||
|
||||
MainUtil.sendMessage(player, "&7 - Initializing map");
|
||||
|
||||
final HashMap<UUID, UUID> uCMap = new HashMap<>();
|
||||
final HashMap<UUID, UUID> uCReverse = new HashMap<>();
|
||||
|
||||
MainUtil.sendMessage(player, "&7 - Collecting playerdata");
|
||||
|
||||
final HashSet<String> worlds = new HashSet<>();
|
||||
worlds.add(WorldUtil.IMP.getMainWorld());
|
||||
worlds.add("world");
|
||||
final HashSet<UUID> uuids = new HashSet<>();
|
||||
final HashSet<String> names = new HashSet<>();
|
||||
for (final String worldname : worlds) {
|
||||
final File playerdataFolder = new File(worldname + File.separator + "playerdata");
|
||||
String[] dat = playerdataFolder.list(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(final File f, final String s) {
|
||||
return s.endsWith(".dat");
|
||||
}
|
||||
});
|
||||
if (dat != null)
|
||||
for (final String current : dat) {
|
||||
final String s = current.replaceAll(".dat$", "");
|
||||
try {
|
||||
final UUID uuid = UUID.fromString(s);
|
||||
uuids.add(uuid);
|
||||
} catch (final Exception e) {
|
||||
MainUtil.sendMessage(player, C.PREFIX.s() + "Invalid playerdata: " + current);
|
||||
}
|
||||
}
|
||||
final File playersFolder = new File(worldname + File.separator + "players");
|
||||
dat = playersFolder.list(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(final File f, final String s) {
|
||||
return s.endsWith(".dat");
|
||||
}
|
||||
});
|
||||
if (dat != null) {
|
||||
for (final String current : dat) {
|
||||
names.add(current.replaceAll(".dat$", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MainUtil.sendMessage(player, "&7 - Populating map");
|
||||
UUID uuid2;
|
||||
final UUIDWrapper wrapper = new DefaultUUIDWrapper();
|
||||
for (UUID uuid : uuids) {
|
||||
try {
|
||||
final OfflinePlotPlayer op = wrapper.getOfflinePlayer(uuid);
|
||||
uuid = currentUUIDWrapper.getUUID(op);
|
||||
uuid2 = newWrapper.getUUID(op);
|
||||
if (!uuid.equals(uuid2) && !uCMap.containsKey(uuid) && !uCReverse.containsKey(uuid2)) {
|
||||
uCMap.put(uuid, uuid2);
|
||||
uCReverse.put(uuid2, uuid);
|
||||
}
|
||||
} catch (final Throwable e) {
|
||||
MainUtil.sendMessage(player, C.PREFIX.s() + "&6Invalid playerdata: " + uuid.toString() + ".dat");
|
||||
}
|
||||
}
|
||||
for (final String name : names) {
|
||||
final UUID uuid = currentUUIDWrapper.getUUID(name);
|
||||
uuid2 = newWrapper.getUUID(name);
|
||||
if (!uuid.equals(uuid2)) {
|
||||
uCMap.put(uuid, uuid2);
|
||||
uCReverse.put(uuid2, uuid);
|
||||
}
|
||||
}
|
||||
if (uCMap.isEmpty()) {
|
||||
MainUtil.sendMessage(player, "&c - Error! Attempting to repopulate");
|
||||
for (final OfflinePlotPlayer op : currentUUIDWrapper.getOfflinePlayers()) {
|
||||
if (op.getLastPlayed() != 0) {
|
||||
// String name = op.getName();
|
||||
// StringWrapper wrap = new StringWrapper(name);
|
||||
final UUID uuid = currentUUIDWrapper.getUUID(op);
|
||||
uuid2 = newWrapper.getUUID(op);
|
||||
if (!uuid.equals(uuid2)) {
|
||||
uCMap.put(uuid, uuid2);
|
||||
uCReverse.put(uuid2, uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (uCMap.isEmpty()) {
|
||||
MainUtil.sendMessage(player, "&cError. Failed to collect UUIDs!");
|
||||
return false;
|
||||
} else {
|
||||
MainUtil.sendMessage(player, "&a - Successfully repopulated");
|
||||
}
|
||||
}
|
||||
|
||||
MainUtil.sendMessage(player, "&7 - Replacing cache");
|
||||
TaskManager.runTaskAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (final Entry<UUID, UUID> entry : uCMap.entrySet()) {
|
||||
final String name = UUIDHandler.getName(entry.getKey());
|
||||
if (name != null) {
|
||||
UUIDHandler.add(new StringWrapper(name), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
MainUtil.sendMessage(player, "&7 - Scanning for applicable files (uuids.txt)");
|
||||
|
||||
final File file = new File(PS.get().IMP.getDirectory(), "uuids.txt");
|
||||
if (file.exists()) {
|
||||
try {
|
||||
final List<String> lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8);
|
||||
for (String line : lines) {
|
||||
try {
|
||||
line = line.trim();
|
||||
if (line.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
line = line.replaceAll("[\\|][0-9]+[\\|][0-9]+[\\|]", "");
|
||||
final String[] split = line.split("\\|");
|
||||
final String name = split[0];
|
||||
if (name.isEmpty() || name.length() > 16 || !StringMan.isAlphanumericUnd(name)) {
|
||||
continue;
|
||||
}
|
||||
final UUID old = currentUUIDWrapper.getUUID(name);
|
||||
if (old == null) {
|
||||
continue;
|
||||
}
|
||||
final UUID now = newWrapper.getUUID(name);
|
||||
UUIDHandler.add(new StringWrapper(name), now);
|
||||
uCMap.put(old, now);
|
||||
uCReverse.put(now, old);
|
||||
} catch (final Exception e2) {
|
||||
e2.printStackTrace();
|
||||
}
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
MainUtil.sendMessage(player, "&7 - Replacing wrapper");
|
||||
UUIDHandler.setUUIDWrapper(newWrapper);
|
||||
|
||||
MainUtil.sendMessage(player, "&7 - Updating plot objects");
|
||||
|
||||
for (final Plot plot : PS.get().getPlots()) {
|
||||
final UUID value = uCMap.get(plot.owner);
|
||||
if (value != null) {
|
||||
plot.owner = value;
|
||||
}
|
||||
plot.getTrusted().clear();
|
||||
plot.getMembers().clear();
|
||||
plot.getDenied().clear();
|
||||
}
|
||||
|
||||
MainUtil.sendMessage(player, "&7 - Deleting database");
|
||||
final AbstractDB database = DBFunc.dbManager;
|
||||
final boolean result = database.deleteTables();
|
||||
|
||||
MainUtil.sendMessage(player, "&7 - Creating tables");
|
||||
|
||||
try {
|
||||
database.createTables();
|
||||
if (!result) {
|
||||
MainUtil.sendMessage(player, "&cConversion failed! Attempting recovery");
|
||||
for (final Plot plot : PS.get().getPlots()) {
|
||||
final UUID value = uCReverse.get(plot.owner);
|
||||
if (value != null) {
|
||||
plot.owner = value;
|
||||
}
|
||||
}
|
||||
database.createPlotsAndData(new ArrayList<>(PS.get().getPlots()), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MainUtil.sendMessage(player, "&6Recovery was successful!");
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
if (newWrapper instanceof OfflineUUIDWrapper) {
|
||||
PS.get().config.set("UUID.force-lowercase", false);
|
||||
PS.get().config.set("UUID.offline", true);
|
||||
} else if (newWrapper instanceof DefaultUUIDWrapper) {
|
||||
PS.get().config.set("UUID.force-lowercase", false);
|
||||
PS.get().config.set("UUID.offline", false);
|
||||
}
|
||||
try {
|
||||
PS.get().config.save(PS.get().configFile);
|
||||
} catch (IOException e) {
|
||||
MainUtil.sendMessage(player, "Could not save configuration. It will need to be manuall set!");
|
||||
}
|
||||
|
||||
MainUtil.sendMessage(player, "&7 - Populating tables");
|
||||
|
||||
TaskManager.runTaskAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final ArrayList<Plot> plots = new ArrayList<>(PS.get().getPlots());
|
||||
database.createPlotsAndData(plots, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MainUtil.sendMessage(player, "&aConversion complete!");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
MainUtil.sendMessage(player, "&aIt is now safe for players to join");
|
||||
MainUtil.sendMessage(player, "&cConversion is still in progress, you will be notified when it is complete");
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
package com.plotsquared.bukkit.database.plotme;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
|
||||
import com.intellectualcrafters.configuration.file.FileConfiguration;
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
|
||||
public abstract class APlotMeConnector {
|
||||
public abstract Connection getPlotMeConnection(final String plugin, final FileConfiguration plotConfig, final String dataFolder);
|
||||
|
||||
public abstract HashMap<String, HashMap<PlotId, Plot>> getPlotMePlots(final Connection connection) throws SQLException;
|
||||
|
||||
public abstract boolean accepts(final String version);
|
||||
|
||||
public String getWorld(final String world) {
|
||||
for (final World newworld : Bukkit.getWorlds()) {
|
||||
if (newworld.getName().equalsIgnoreCase(world)) {
|
||||
return newworld.getName();
|
||||
}
|
||||
}
|
||||
return world;
|
||||
}
|
||||
|
||||
public boolean isValidConnection(final Connection connection) {
|
||||
return connection != null;
|
||||
}
|
||||
|
||||
public void copyConfig(final FileConfiguration plotConfig, final String world, final String actualWorldName) {
|
||||
final Integer pathwidth = plotConfig.getInt("worlds." + world + ".PathWidth"); //
|
||||
PS.get().config.set("worlds." + actualWorldName + ".road.width", pathwidth);
|
||||
final Integer plotsize = plotConfig.getInt("worlds." + world + ".PlotSize"); //
|
||||
PS.get().config.set("worlds." + actualWorldName + ".plot.size", plotsize);
|
||||
final String wallblock = plotConfig.getString("worlds." + world + ".WallBlockId"); //
|
||||
PS.get().config.set("worlds." + actualWorldName + ".wall.block", wallblock);
|
||||
final String floor = plotConfig.getString("worlds." + world + ".PlotFloorBlockId"); //
|
||||
PS.get().config.set("worlds." + actualWorldName + ".plot.floor", Collections.singletonList(floor));
|
||||
final String filling = plotConfig.getString("worlds." + world + ".PlotFillingBlockId"); //
|
||||
PS.get().config.set("worlds." + actualWorldName + ".plot.filling", Collections.singletonList(filling));
|
||||
final String road = plotConfig.getString("worlds." + world + ".RoadMainBlockId");
|
||||
PS.get().config.set("worlds." + actualWorldName + ".road.block", road);
|
||||
Integer height = plotConfig.getInt("worlds." + world + ".RoadHeight"); //
|
||||
PS.get().config.set("worlds." + actualWorldName + ".road.height", height);
|
||||
}
|
||||
|
||||
public Location getPlotTopLocAbs(final int path, final int plot, final PlotId plotid) {
|
||||
final int px = plotid.x;
|
||||
final int pz = plotid.y;
|
||||
final int x = (px * (path + plot)) - ((int) Math.floor(path / 2)) - 1;
|
||||
final int z = (pz * (path + plot)) - ((int) Math.floor(path / 2)) - 1;
|
||||
return new Location(null, x, 256, z);
|
||||
}
|
||||
|
||||
public Location getPlotBottomLocAbs(final int path, final int plot, final PlotId plotid) {
|
||||
final int px = plotid.x;
|
||||
final int pz = plotid.y;
|
||||
final int x = (px * (path + plot)) - plot - ((int) Math.floor(path / 2)) - 1;
|
||||
final int z = (pz * (path + plot)) - plot - ((int) Math.floor(path / 2)) - 1;
|
||||
return new Location(null, x, 1, z);
|
||||
}
|
||||
|
||||
public void setMerged(final HashMap<String, HashMap<PlotId, boolean[]>> merges, final String world, final PlotId id, final int direction) {
|
||||
final HashMap<PlotId, boolean[]> plots = merges.get(world);
|
||||
PlotId id2;
|
||||
switch (direction) {
|
||||
case 0: {
|
||||
id2 = new PlotId(id.x, id.y);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
id2 = new PlotId(id.x, id.y);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
id2 = new PlotId(id.x, id.y);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
id2 = new PlotId(id.x, id.y);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return;
|
||||
}
|
||||
}
|
||||
boolean[] merge1;
|
||||
boolean[] merge2;
|
||||
if (plots.containsKey(id)) {
|
||||
merge1 = plots.get(id);
|
||||
} else {
|
||||
merge1 = new boolean[] { false, false, false, false };
|
||||
}
|
||||
if (plots.containsKey(id2)) {
|
||||
merge2 = plots.get(id2);
|
||||
} else {
|
||||
merge2 = new boolean[] { false, false, false, false };
|
||||
}
|
||||
merge1[direction] = true;
|
||||
merge2[(direction + 2) % 4] = true;
|
||||
plots.put(id, merge1);
|
||||
plots.put(id2, merge1);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,267 @@
|
||||
package com.plotsquared.bukkit.database.plotme;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.intellectualcrafters.configuration.file.FileConfiguration;
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.config.Settings;
|
||||
import com.intellectualcrafters.plot.database.DBFunc;
|
||||
import com.intellectualcrafters.plot.database.SQLite;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotArea;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
import com.intellectualcrafters.plot.object.StringWrapper;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandler;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ClassicPlotMeConnector extends APlotMeConnector {
|
||||
|
||||
private String plugin;
|
||||
private String prefix;
|
||||
|
||||
@Override
|
||||
public Connection getPlotMeConnection(final String plugin, final FileConfiguration plotConfig, final String dataFolder) {
|
||||
this.plugin = plugin.toLowerCase();
|
||||
prefix = plotConfig.getString("mySQLprefix");
|
||||
if (prefix == null) {
|
||||
prefix = plugin.toLowerCase();
|
||||
}
|
||||
try {
|
||||
if (plotConfig.getBoolean("usemySQL")) {
|
||||
final String user = plotConfig.getString("mySQLuname");
|
||||
final String password = plotConfig.getString("mySQLpass");
|
||||
final String con = plotConfig.getString("mySQLconn");
|
||||
return DriverManager.getConnection(con, user, password);
|
||||
// return new MySQL(plotsquared, hostname, port, database, username, password)
|
||||
} else {
|
||||
return new SQLite(dataFolder + File.separator + "plots.db").openConnection();
|
||||
}
|
||||
} catch (SQLException | ClassNotFoundException ignored) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<String, HashMap<PlotId, Plot>> getPlotMePlots(final Connection connection) throws SQLException {
|
||||
final HashMap<String, Integer> plotWidth = new HashMap<>();
|
||||
final HashMap<String, Integer> roadWidth = new HashMap<>();
|
||||
final HashMap<String, HashMap<PlotId, Plot>> plots = new HashMap<>();
|
||||
final HashMap<String, HashMap<PlotId, boolean[]>> merges = new HashMap<>();
|
||||
PreparedStatement stmt = connection.prepareStatement("SELECT * FROM `" + prefix + "Plots`");
|
||||
ResultSet r = stmt.executeQuery();
|
||||
String column = null;
|
||||
final boolean checkUUID = DBFunc.hasColumn(r, "ownerid");
|
||||
final boolean checkUUID2 = DBFunc.hasColumn(r, "ownerId");
|
||||
if (checkUUID) {
|
||||
column = "ownerid";
|
||||
} else if (checkUUID2) {
|
||||
column = "ownerId";
|
||||
}
|
||||
final boolean merge = !"plotme".equalsIgnoreCase(plugin) && Settings.CONVERT_PLOTME;
|
||||
int missing = 0;
|
||||
while (r.next()) {
|
||||
final PlotId id = new PlotId(r.getInt("idX"), r.getInt("idZ"));
|
||||
final String name = r.getString("owner");
|
||||
final String world = LikePlotMeConverter.getWorld(r.getString("world"));
|
||||
if (!plots.containsKey(world)) {
|
||||
plots.put(world, new HashMap<PlotId, Plot>());
|
||||
if (merge) {
|
||||
final int plot = PS.get().config.getInt("worlds." + world + ".plot.size");
|
||||
final int path = PS.get().config.getInt("worlds." + world + ".road.width");
|
||||
plotWidth.put(world, plot);
|
||||
roadWidth.put(world, path);
|
||||
merges.put(world, new HashMap<PlotId, boolean[]>());
|
||||
}
|
||||
}
|
||||
if (merge) {
|
||||
final int tx = r.getInt("topX");
|
||||
final int tz = r.getInt("topZ");
|
||||
final int bx = r.getInt("bottomX") - 1;
|
||||
final int bz = r.getInt("bottomZ") - 1;
|
||||
final int path = roadWidth.get(world);
|
||||
final int plot = plotWidth.get(world);
|
||||
final Location top = getPlotTopLocAbs(path, plot, id);
|
||||
final Location bot = getPlotBottomLocAbs(path, plot, id);
|
||||
if (tx > top.getX()) {
|
||||
setMerged(merges, world, id, 1);
|
||||
}
|
||||
if (tz > top.getZ()) {
|
||||
setMerged(merges, world, id, 2);
|
||||
}
|
||||
if (bx < bot.getX()) {
|
||||
setMerged(merges, world, id, 3);
|
||||
}
|
||||
if (bz > bot.getZ()) {
|
||||
setMerged(merges, world, id, 0);
|
||||
}
|
||||
}
|
||||
UUID owner = UUIDHandler.getUUID(name, null);
|
||||
if (owner == null) {
|
||||
if ("*".equals(name)) {
|
||||
owner = DBFunc.everyone;
|
||||
} else {
|
||||
if (checkUUID || checkUUID2) {
|
||||
try {
|
||||
final byte[] bytes = r.getBytes(column);
|
||||
if (bytes != null) {
|
||||
try {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(bytes);
|
||||
final long high = bb.getLong();
|
||||
final long low = bb.getLong();
|
||||
owner = new UUID(high, low);
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
owner = UUID.nameUUIDFromBytes(bytes);
|
||||
}
|
||||
UUIDHandler.add(new StringWrapper(name), owner);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (owner == null) {
|
||||
if (!name.isEmpty()) {
|
||||
owner = UUID.nameUUIDFromBytes(("OfflinePlayer:" + name.toLowerCase()).getBytes(Charsets.UTF_8));
|
||||
}
|
||||
PS.log("&cCould not identify owner for plot: " + id + " -> '" + name + "'");
|
||||
missing++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
UUIDHandler.add(new StringWrapper(name), owner);
|
||||
}
|
||||
final Plot plot = new Plot(PlotArea.createGeneric(world), id, owner);
|
||||
plots.get(world).put(id, plot);
|
||||
}
|
||||
if (missing > 0) {
|
||||
PS.log("&cSome names could not be identified:");
|
||||
PS.log("&7 - Empty quotes mean PlotMe just stored an unowned plot in the database");
|
||||
PS.log("&7 - Names you have never seen before could be from people mistyping commands");
|
||||
PS.log("&7 - Converting from a non-uuid version of PlotMe can't identify owners if the playerdata files are deleted (these plots will remain unknown until the player connects)");
|
||||
}
|
||||
|
||||
for (final Entry<String, HashMap<PlotId, boolean[]>> entry : merges.entrySet()) {
|
||||
final String world = entry.getKey();
|
||||
for (final Entry<PlotId, boolean[]> entry2 : entry.getValue().entrySet()) {
|
||||
final HashMap<PlotId, Plot> newplots = plots.get(world);
|
||||
final Plot plot = newplots.get(entry2.getKey());
|
||||
if (plot != null) {
|
||||
plot.setMerged(entry2.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r.close();
|
||||
stmt.close();
|
||||
|
||||
try {
|
||||
|
||||
PS.log(" - " + prefix + "Denied");
|
||||
stmt = connection.prepareStatement("SELECT * FROM `" + prefix + "Denied`");
|
||||
r = stmt.executeQuery();
|
||||
|
||||
while (r.next()) {
|
||||
final PlotId id = new PlotId(r.getInt("idX"), r.getInt("idZ"));
|
||||
final String name = r.getString("player");
|
||||
final String world = LikePlotMeConverter.getWorld(r.getString("world"));
|
||||
UUID denied = UUIDHandler.getUUID(name, null);
|
||||
if (denied == null) {
|
||||
if ("*".equals(name)) {
|
||||
denied = DBFunc.everyone;
|
||||
} else {
|
||||
if (DBFunc.hasColumn(r, "playerid")) {
|
||||
try {
|
||||
final byte[] bytes = r.getBytes("playerid");
|
||||
if (bytes != null) {
|
||||
try {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(bytes);
|
||||
final long high = bb.getLong();
|
||||
final long low = bb.getLong();
|
||||
denied = new UUID(high, low);
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
denied = UUID.nameUUIDFromBytes(bytes);
|
||||
}
|
||||
UUIDHandler.add(new StringWrapper(name), denied);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (denied == null) {
|
||||
PS.log("&6Could not identify denied for plot: " + id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (plots.get(world).containsKey(id)) {
|
||||
plots.get(world).get(id).getDenied().add(denied);
|
||||
}
|
||||
}
|
||||
|
||||
stmt = connection.prepareStatement("SELECT * FROM `" + plugin + "Allowed`");
|
||||
r = stmt.executeQuery();
|
||||
|
||||
while (r.next()) {
|
||||
final PlotId id = new PlotId(r.getInt("idX"), r.getInt("idZ"));
|
||||
final String name = r.getString("player");
|
||||
final String world = LikePlotMeConverter.getWorld(r.getString("world"));
|
||||
UUID helper = UUIDHandler.getUUID(name, null);
|
||||
if (helper == null) {
|
||||
if ("*".equals(name)) {
|
||||
helper = DBFunc.everyone;
|
||||
} else {
|
||||
if (DBFunc.hasColumn(r, "playerid")) {
|
||||
try {
|
||||
final byte[] bytes = r.getBytes("playerid");
|
||||
if (bytes != null) {
|
||||
try {
|
||||
final ByteBuffer bb = ByteBuffer.wrap(bytes);
|
||||
final long high = bb.getLong();
|
||||
final long low = bb.getLong();
|
||||
helper = new UUID(high, low);
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
helper = UUID.nameUUIDFromBytes(bytes);
|
||||
}
|
||||
UUIDHandler.add(new StringWrapper(name), helper);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (helper == null) {
|
||||
PS.log("&6Could not identify helper for plot: " + id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (plots.get(world).containsKey(id)) {
|
||||
plots.get(world).get(id).getTrusted().add(helper);
|
||||
}
|
||||
}
|
||||
|
||||
r.close();
|
||||
stmt.close();
|
||||
|
||||
} catch (SQLException e) {
|
||||
}
|
||||
return plots;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accepts(final String version) {
|
||||
return version == null || PS.get().canUpdate(version, "0.17.0") || PS.get().canUpdate("0.999.999", version);
|
||||
}
|
||||
}
|
@ -0,0 +1,404 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.database.plotme;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.sql.Connection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
|
||||
import com.intellectualcrafters.configuration.file.FileConfiguration;
|
||||
import com.intellectualcrafters.configuration.file.YamlConfiguration;
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.config.Settings;
|
||||
import com.intellectualcrafters.plot.database.DBFunc;
|
||||
import com.intellectualcrafters.plot.generator.HybridGen;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotArea;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
import com.plotsquared.bukkit.generator.BukkitPlotGenerator;
|
||||
|
||||
/**
|
||||
* Created 2014-08-17 for PlotSquared
|
||||
*
|
||||
|
||||
|
||||
*/
|
||||
public class LikePlotMeConverter {
|
||||
private final String plugin;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param plugin Plugin Used to run the converter
|
||||
*/
|
||||
public LikePlotMeConverter(final String plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public static String getWorld(final String world) {
|
||||
for (final World newworld : Bukkit.getWorlds()) {
|
||||
if (newworld.getName().equalsIgnoreCase(world)) {
|
||||
return newworld.getName();
|
||||
}
|
||||
}
|
||||
return world;
|
||||
}
|
||||
|
||||
private void sendMessage(final String message) {
|
||||
PS.debug("&3PlotMe&8->&3PlotSquared&8: &7" + message);
|
||||
}
|
||||
|
||||
public String getPlotMePath() {
|
||||
return new File(".").getAbsolutePath() + File.separator + "plugins" + File.separator + plugin + File.separator;
|
||||
}
|
||||
|
||||
public String getAthionPlotsPath() {
|
||||
return new File(".").getAbsolutePath() + File.separator + "plugins" + File.separator + plugin + File.separator;
|
||||
}
|
||||
|
||||
public FileConfiguration getPlotMeConfig(final String dataFolder) {
|
||||
final File plotMeFile = new File(dataFolder + "config.yml");
|
||||
if (!plotMeFile.exists()) {
|
||||
return null;
|
||||
}
|
||||
return YamlConfiguration.loadConfiguration(plotMeFile);
|
||||
}
|
||||
|
||||
public Set<String> getPlotMeWorlds(final FileConfiguration plotConfig) {
|
||||
return plotConfig.getConfigurationSection("worlds").getKeys(false);
|
||||
}
|
||||
|
||||
public void mergeWorldYml(final String plugin, FileConfiguration plotConfig) {
|
||||
try {
|
||||
File genConfig = new File("plugins" + File.separator + plugin + File.separator + "PlotMe-DefaultGenerator" + File.separator + "config.yml");
|
||||
if (genConfig.exists()) {
|
||||
YamlConfiguration yml = YamlConfiguration.loadConfiguration(genConfig);
|
||||
for (String key : yml.getKeys(true)) {
|
||||
if (!plotConfig.contains(key)) {
|
||||
plotConfig.set(key, yml.get(key));
|
||||
}
|
||||
}
|
||||
genConfig.delete();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateWorldYml(final String plugin, final String location) {
|
||||
try {
|
||||
final Path path = Paths.get(location);
|
||||
final File file = new File(location);
|
||||
if (!file.exists()) {
|
||||
return;
|
||||
}
|
||||
final Charset charset = StandardCharsets.UTF_8;
|
||||
String content = new String(Files.readAllBytes(path), charset);
|
||||
content = content.replaceAll("PlotMe-DefaultGenerator", "PlotSquared");
|
||||
content = content.replaceAll(plugin, "PlotSquared");
|
||||
Files.write(path, content.getBytes(charset));
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean run(final APlotMeConnector connector) {
|
||||
try {
|
||||
final String dataFolder = getPlotMePath();
|
||||
final FileConfiguration plotConfig = getPlotMeConfig(dataFolder);
|
||||
if (plotConfig == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String version = plotConfig.getString("Version");
|
||||
if (version == null) {
|
||||
version = plotConfig.getString("version");
|
||||
}
|
||||
if (!connector.accepts(version)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PS.debug("&3Using connector: " + connector.getClass().getCanonicalName());
|
||||
|
||||
final Connection connection = connector.getPlotMeConnection(plugin, plotConfig, dataFolder);
|
||||
|
||||
if (!connector.isValidConnection(connection)) {
|
||||
sendMessage("Cannot connect to PlotMe DB. Conversion process will not continue");
|
||||
return false;
|
||||
}
|
||||
|
||||
sendMessage(plugin + " conversion has started. To disable this, please set 'plotme-convert.enabled' to false in the 'settings.yml'");
|
||||
|
||||
mergeWorldYml(plugin, plotConfig);
|
||||
|
||||
sendMessage("Connecting to " + plugin + " DB");
|
||||
|
||||
int plotCount = 0;
|
||||
final ArrayList<Plot> createdPlots = new ArrayList<>();
|
||||
|
||||
sendMessage("Collecting plot data");
|
||||
|
||||
final String dbPrefix = plugin.toLowerCase();
|
||||
sendMessage(" - " + dbPrefix + "Plots");
|
||||
final Set<String> worlds = getPlotMeWorlds(plotConfig);
|
||||
|
||||
if (Settings.CONVERT_PLOTME) {
|
||||
sendMessage("Updating bukkit.yml");
|
||||
updateWorldYml(plugin, "bukkit.yml");
|
||||
updateWorldYml(plugin, "plugins/Multiverse-Core/worlds.yml");
|
||||
for (final String world : plotConfig.getConfigurationSection("worlds").getKeys(false)) {
|
||||
sendMessage("Copying config for: " + world);
|
||||
try {
|
||||
final String actualWorldName = getWorld(world);
|
||||
connector.copyConfig(plotConfig, world, actualWorldName);
|
||||
PS.get().config.save(PS.get().configFile);
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
sendMessage("&c-- &lFailed to save configuration for world '" + world + "'\nThis will need to be done using the setup command, or manually");
|
||||
}
|
||||
}
|
||||
}
|
||||
final HashMap<String, HashMap<PlotId, Plot>> plots = connector.getPlotMePlots(connection);
|
||||
for (final Entry<String, HashMap<PlotId, Plot>> entry : plots.entrySet()) {
|
||||
plotCount += entry.getValue().size();
|
||||
}
|
||||
if (!Settings.CONVERT_PLOTME) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sendMessage(" - " + dbPrefix + "Allowed");
|
||||
|
||||
sendMessage("Collected " + plotCount + " plots from PlotMe");
|
||||
final File PLOTME_DG_FILE = new File(dataFolder + File.separator + "PlotMe-DefaultGenerator" + File.separator + "config.yml");
|
||||
if (PLOTME_DG_FILE.exists()) {
|
||||
final YamlConfiguration PLOTME_DG_YML = YamlConfiguration.loadConfiguration(PLOTME_DG_FILE);
|
||||
try {
|
||||
for (final String world : plots.keySet()) {
|
||||
final String actualWorldName = getWorld(world);
|
||||
final String plotMeWorldName = world.toLowerCase();
|
||||
Integer pathwidth = PLOTME_DG_YML.getInt("worlds." + plotMeWorldName + ".PathWidth"); //
|
||||
/*
|
||||
* TODO: dead code
|
||||
*
|
||||
if (pathwidth == null) {
|
||||
pathwidth = 7;
|
||||
}
|
||||
*/
|
||||
PS.get().config.set("worlds." + world + ".road.width", pathwidth);
|
||||
|
||||
Integer pathheight = PLOTME_DG_YML.getInt("worlds." + plotMeWorldName + ".RoadHeight"); //
|
||||
if ((pathheight == null) || (pathheight == 0)) {
|
||||
pathheight = 64;
|
||||
}
|
||||
PS.get().config.set("worlds." + world + ".road.height", pathheight);
|
||||
PS.get().config.set("worlds." + world + ".wall.height", pathheight);
|
||||
PS.get().config.set("worlds." + world + ".plot.height", pathheight);
|
||||
Integer plotsize = PLOTME_DG_YML.getInt("worlds." + plotMeWorldName + ".PlotSize"); //
|
||||
if ((plotsize == null) || (plotsize == 0)) {
|
||||
plotsize = 32;
|
||||
}
|
||||
PS.get().config.set("worlds." + world + ".plot.size", plotsize);
|
||||
String wallblock = PLOTME_DG_YML.getString("worlds." + plotMeWorldName + ".WallBlock"); //
|
||||
if (wallblock == null) {
|
||||
wallblock = "44";
|
||||
}
|
||||
PS.get().config.set("worlds." + world + ".wall.block", wallblock);
|
||||
String floor = PLOTME_DG_YML.getString("worlds." + plotMeWorldName + ".PlotFloorBlock"); //
|
||||
if (floor == null) {
|
||||
floor = "2";
|
||||
}
|
||||
PS.get().config.set("worlds." + world + ".plot.floor", Collections.singletonList(floor));
|
||||
String filling = PLOTME_DG_YML.getString("worlds." + plotMeWorldName + ".FillBlock"); //
|
||||
if (filling == null) {
|
||||
filling = "3";
|
||||
}
|
||||
PS.get().config.set("worlds." + world + ".plot.filling", Collections.singletonList(filling));
|
||||
String road = PLOTME_DG_YML.getString("worlds." + plotMeWorldName + ".RoadMainBlock");
|
||||
if (road == null) {
|
||||
road = "5";
|
||||
}
|
||||
PS.get().config.set("worlds." + world + ".road.block", road);
|
||||
Integer height = PLOTME_DG_YML.getInt("worlds." + plotMeWorldName + ".RoadHeight"); //
|
||||
if (height == 0) {
|
||||
height = PLOTME_DG_YML.getInt("worlds." + plotMeWorldName + ".GroundHeight"); //
|
||||
if (height == 0) {
|
||||
height = 64;
|
||||
}
|
||||
}
|
||||
PS.get().config.set("worlds." + actualWorldName + ".road.height", height);
|
||||
PS.get().config.set("worlds." + actualWorldName + ".plot.height", height);
|
||||
PS.get().config.set("worlds." + actualWorldName + ".wall.height", height);
|
||||
PS.get().config.save(PS.get().configFile);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
for (Entry<String, HashMap<PlotId, Plot>> entry : plots.entrySet()) {
|
||||
String world = entry.getKey();
|
||||
PlotArea area = PS.get().getPlotArea(world, null);
|
||||
int duplicate = 0;
|
||||
if (area != null) {
|
||||
for (Entry<PlotId, Plot> entry2 : entry.getValue().entrySet()) {
|
||||
if (area.getOwnedPlotAbs(entry2.getKey()) != null) {
|
||||
duplicate++;
|
||||
} else {
|
||||
createdPlots.add(entry2.getValue());
|
||||
}
|
||||
}
|
||||
if (duplicate > 0) {
|
||||
PS.debug("&c[WARNING] Found " + duplicate + " duplicate plots already in DB for world: '" + world + "'. Have you run the converter already?");
|
||||
}
|
||||
} else {
|
||||
if (PS.get().plots_tmp != null) {
|
||||
HashMap<PlotId, Plot> map = PS.get().plots_tmp.get(world);
|
||||
if (map != null) {
|
||||
for (Entry<PlotId, Plot> entry2 : entry.getValue().entrySet()) {
|
||||
if (map.containsKey(entry2.getKey())) {
|
||||
duplicate++;
|
||||
} else {
|
||||
createdPlots.add(entry2.getValue());
|
||||
}
|
||||
}
|
||||
if (duplicate > 0) {
|
||||
PS.debug("&c[WARNING] Found " + duplicate + " duplicate plots already in DB for world: '" + world + "'. Have you run the converter already?");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
createdPlots.addAll(entry.getValue().values());
|
||||
}
|
||||
}
|
||||
sendMessage("Creating plot DB");
|
||||
Thread.sleep(1000);
|
||||
final AtomicBoolean done = new AtomicBoolean(false);
|
||||
DBFunc.createPlotsAndData(createdPlots, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (done.get()) {
|
||||
done();
|
||||
sendMessage("&aDatabase conversion is now complete!");
|
||||
PS.debug("&c - Stop the server");
|
||||
PS.debug("&c - Disable 'plotme-convert.enabled' and 'plotme-convert.cache-uuids' in the settings.yml");
|
||||
PS.debug("&c - Correct any generator settings that haven't copied to 'settings.yml' properly");
|
||||
PS.debug("&c - Start the server");
|
||||
PS.get().setPlots(DBFunc.getPlots());
|
||||
} else {
|
||||
sendMessage("&cPlease wait until database conversion is complete. You will be notified with instructions when this happens!");
|
||||
done.set(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
sendMessage("Saving configuration...");
|
||||
try {
|
||||
PS.get().config.save(PS.get().configFile);
|
||||
} catch (final IOException e) {
|
||||
sendMessage(" - &cFailed to save configuration.");
|
||||
}
|
||||
TaskManager.runTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
boolean MV = false;
|
||||
boolean MW = false;
|
||||
if ((Bukkit.getPluginManager().getPlugin("Multiverse-Core") != null) && Bukkit.getPluginManager().getPlugin("Multiverse-Core").isEnabled()) {
|
||||
MV = true;
|
||||
} else if ((Bukkit.getPluginManager().getPlugin("MultiWorld") != null) && Bukkit.getPluginManager().getPlugin("MultiWorld").isEnabled()) {
|
||||
MW = true;
|
||||
}
|
||||
for (final String worldname : worlds) {
|
||||
final World world = Bukkit.getWorld(getWorld(worldname));
|
||||
if (world == null) {
|
||||
sendMessage("&cInvalid world in PlotMe configuration: " + worldname);
|
||||
}
|
||||
final String actualWorldName = world.getName();
|
||||
sendMessage("Reloading generator for world: '" + actualWorldName + "'...");
|
||||
PS.get().removePlotAreas(actualWorldName);
|
||||
if (MV) {
|
||||
// unload world with MV
|
||||
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "mv unload " + actualWorldName);
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (final InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
// load world with MV
|
||||
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "mv import " + actualWorldName + " normal -g PlotSquared");
|
||||
} else if (MW) {
|
||||
// unload world with MW
|
||||
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "mw unload " + actualWorldName);
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (final InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
// load world with MW
|
||||
Bukkit.getServer().dispatchCommand(Bukkit.getServer().getConsoleSender(), "mw create " + actualWorldName + " plugin:PlotSquared");
|
||||
} else {
|
||||
// Load using Bukkit API
|
||||
// - User must set generator manually
|
||||
Bukkit.getServer().unloadWorld(world, true);
|
||||
final World myworld = WorldCreator.name(actualWorldName).generator(new BukkitPlotGenerator(new HybridGen())).createWorld();
|
||||
myworld.save();
|
||||
}
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (done.get()) {
|
||||
done();
|
||||
sendMessage("&aDatabase conversion is now complete!");
|
||||
PS.debug("&c - Stop the server");
|
||||
PS.debug("&c - Disable 'plotme-convert.enabled' and 'plotme-convert.cache-uuids' in the settings.yml");
|
||||
PS.debug("&c - Correct any generator settings that haven't copied to 'settings.yml' properly");
|
||||
PS.debug("&c - Start the server");
|
||||
} else {
|
||||
sendMessage("&cPlease wait until database conversion is complete. You will be notified with instructions when this happens!");
|
||||
done.set(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
PS.debug("&/end/");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void done() {
|
||||
PS.get().setPlots(DBFunc.getPlots());
|
||||
}
|
||||
}
|
@ -0,0 +1,200 @@
|
||||
package com.plotsquared.bukkit.database.plotme;
|
||||
|
||||
import com.intellectualcrafters.configuration.file.FileConfiguration;
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.config.Settings;
|
||||
import com.intellectualcrafters.plot.database.DBFunc;
|
||||
import com.intellectualcrafters.plot.database.SQLite;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotArea;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
import com.intellectualcrafters.plot.object.StringWrapper;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandler;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PlotMeConnector_017 extends APlotMeConnector {
|
||||
private String plugin;
|
||||
|
||||
@Override
|
||||
public Connection getPlotMeConnection(final String plugin, final FileConfiguration plotConfig, final String dataFolder) {
|
||||
this.plugin = plugin.toLowerCase();
|
||||
try {
|
||||
if (plotConfig.getBoolean("usemySQL")) {
|
||||
final String user = plotConfig.getString("mySQLuname");
|
||||
final String password = plotConfig.getString("mySQLpass");
|
||||
final String con = plotConfig.getString("mySQLconn");
|
||||
return DriverManager.getConnection(con, user, password);
|
||||
} else {
|
||||
final File file = new File(dataFolder + File.separator + "plotmecore.db");
|
||||
if (file.exists()) {
|
||||
return new SQLite(dataFolder + File.separator + "plotmecore.db").openConnection();
|
||||
}
|
||||
return new SQLite(dataFolder + File.separator + "plots.db").openConnection();
|
||||
}
|
||||
} catch (SQLException | ClassNotFoundException e) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<String, HashMap<PlotId, Plot>> getPlotMePlots(final Connection connection) throws SQLException {
|
||||
ResultSet r;
|
||||
PreparedStatement stmt;
|
||||
final HashMap<String, Integer> plotWidth = new HashMap<>();
|
||||
final HashMap<String, Integer> roadWidth = new HashMap<>();
|
||||
final HashMap<Integer, Plot> plots = new HashMap<>();
|
||||
final HashMap<String, HashMap<PlotId, boolean[]>> merges = new HashMap<>();
|
||||
try {
|
||||
stmt = connection.prepareStatement("SELECT * FROM `" + plugin + "core_plots`");
|
||||
r = stmt.executeQuery();
|
||||
} catch (SQLException e) {
|
||||
PS.debug("========= Table does not exist =========");
|
||||
e.printStackTrace();
|
||||
PS.debug("=======================================");
|
||||
PS.debug("&8 - &7The database does not match the version specified in the PlotMe config");
|
||||
PS.debug("&8 - &7Please correct this, or if you are unsure, the most common is 0.16.3");
|
||||
return null;
|
||||
}
|
||||
final boolean checkUUID = DBFunc.hasColumn(r, "ownerID");
|
||||
final boolean merge = !plugin.equals("plotme") && Settings.CONVERT_PLOTME;
|
||||
while (r.next()) {
|
||||
final int key = r.getInt("plot_id");
|
||||
final PlotId id = new PlotId(r.getInt("plotX"), r.getInt("plotZ"));
|
||||
final String name = r.getString("owner");
|
||||
final String world = LikePlotMeConverter.getWorld(r.getString("world"));
|
||||
if (!plots.containsKey(world)) {
|
||||
if (merge) {
|
||||
final int plot = PS.get().config.getInt("worlds." + world + ".plot.size");
|
||||
final int path = PS.get().config.getInt("worlds." + world + ".road.width");
|
||||
plotWidth.put(world, plot);
|
||||
roadWidth.put(world, path);
|
||||
merges.put(world, new HashMap<PlotId, boolean[]>());
|
||||
}
|
||||
}
|
||||
if (merge) {
|
||||
final int tx = r.getInt("topX");
|
||||
final int tz = r.getInt("topZ");
|
||||
final int bx = r.getInt("bottomX") - 1;
|
||||
final int bz = r.getInt("bottomZ") - 1;
|
||||
final int path = roadWidth.get(world);
|
||||
final int plot = plotWidth.get(world);
|
||||
final Location top = getPlotTopLocAbs(path, plot, id);
|
||||
final Location bot = getPlotBottomLocAbs(path, plot, id);
|
||||
if (tx > top.getX()) {
|
||||
setMerged(merges, world, id, 1);
|
||||
}
|
||||
if (tz > top.getZ()) {
|
||||
setMerged(merges, world, id, 2);
|
||||
}
|
||||
if (bx < bot.getX()) {
|
||||
setMerged(merges, world, id, 3);
|
||||
}
|
||||
if (bz > bot.getZ()) {
|
||||
setMerged(merges, world, id, 0);
|
||||
}
|
||||
}
|
||||
UUID owner = UUIDHandler.getUUID(name, null);
|
||||
if (owner == null) {
|
||||
if (name.equals("*")) {
|
||||
owner = DBFunc.everyone;
|
||||
} else {
|
||||
if (checkUUID) {
|
||||
try {
|
||||
final byte[] bytes = r.getBytes("ownerid");
|
||||
if (bytes != null) {
|
||||
owner = UUID.nameUUIDFromBytes(bytes);
|
||||
UUIDHandler.add(new StringWrapper(name), owner);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (owner == null) {
|
||||
PS.log("&cCould not identify owner for plot: " + id + " -> '" + name + "'");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
UUIDHandler.add(new StringWrapper(name), owner);
|
||||
}
|
||||
final Plot plot = new Plot(PlotArea.createGeneric(world), id, owner);
|
||||
plots.put(key, plot);
|
||||
}
|
||||
for (final Entry<Integer, Plot> entry : plots.entrySet()) {
|
||||
final Plot plot = entry.getValue();
|
||||
final HashMap<PlotId, boolean[]> mergeMap = merges.get(plot.getArea().worldname);
|
||||
if (mergeMap != null) {
|
||||
if (mergeMap.containsKey(plot.getId())) {
|
||||
plot.setMerged(mergeMap.get(plot.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
r.close();
|
||||
stmt.close();
|
||||
try {
|
||||
PS.log(" - " + plugin + "core_denied");
|
||||
stmt = connection.prepareStatement("SELECT * FROM `" + plugin + "core_denied`");
|
||||
r = stmt.executeQuery();
|
||||
|
||||
while (r.next()) {
|
||||
final int key = r.getInt("plot_id");
|
||||
final Plot plot = plots.get(key);
|
||||
if (plot == null) {
|
||||
PS.log("&6Denied (" + key + ") references deleted plot; ignoring entry.");
|
||||
continue;
|
||||
}
|
||||
final UUID denied = UUID.fromString(r.getString("player"));
|
||||
plot.getDenied().add(denied);
|
||||
}
|
||||
|
||||
PS.log(" - " + plugin + "core_allowed");
|
||||
stmt = connection.prepareStatement("SELECT * FROM `" + plugin + "core_allowed`");
|
||||
r = stmt.executeQuery();
|
||||
|
||||
while (r.next()) {
|
||||
final int key = r.getInt("plot_id");
|
||||
final Plot plot = plots.get(key);
|
||||
if (plot == null) {
|
||||
PS.log("&6Allowed (" + key + ") references deleted plot; ignoring entry.");
|
||||
continue;
|
||||
}
|
||||
final UUID allowed = UUID.fromString(r.getString("player"));
|
||||
plot.getTrusted().add(allowed);
|
||||
}
|
||||
r.close();
|
||||
stmt.close();
|
||||
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
final HashMap<String, HashMap<PlotId, Plot>> processed = new HashMap<>();
|
||||
|
||||
for (final Entry<Integer, Plot> entry : plots.entrySet()) {
|
||||
final Plot plot = entry.getValue();
|
||||
HashMap<PlotId, Plot> map = processed.get(plot.getArea().worldname);
|
||||
if (map == null) {
|
||||
map = new HashMap<>();
|
||||
processed.put(plot.getArea().worldname, map);
|
||||
}
|
||||
map.put(plot.getId(), plot);
|
||||
}
|
||||
return processed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accepts(final String version) {
|
||||
if (version == null) {
|
||||
return false;
|
||||
}
|
||||
return !PS.get().canUpdate(version, "0.17");
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.events;
|
||||
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.intellectualcrafters.plot.flag.Flag;
|
||||
import com.intellectualcrafters.plot.object.PlotCluster;
|
||||
|
||||
/**
|
||||
* Called when a flag is removed from a plot
|
||||
*
|
||||
|
||||
|
||||
*/
|
||||
public class ClusterFlagRemoveEvent extends Event implements Cancellable {
|
||||
private static HandlerList handlers = new HandlerList();
|
||||
private final PlotCluster cluster;
|
||||
private final Flag flag;
|
||||
private boolean cancelled;
|
||||
|
||||
/**
|
||||
* PlotFlagRemoveEvent: Called when a flag is removed from a plot
|
||||
*
|
||||
* @param flag Flag that was removed
|
||||
* @param cluster PlotCluster from which the flag was removed
|
||||
*/
|
||||
public ClusterFlagRemoveEvent(final Flag flag, final PlotCluster cluster) {
|
||||
this.cluster = cluster;
|
||||
this.flag = flag;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cluster involved
|
||||
*
|
||||
* @return PlotCluster
|
||||
*/
|
||||
public PlotCluster getCluster() {
|
||||
return cluster;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the flag involved
|
||||
*
|
||||
* @return Flag
|
||||
*/
|
||||
public Flag getFlag() {
|
||||
return flag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(final boolean b) {
|
||||
cancelled = b;
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.events;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
|
||||
/**
|
||||
|
||||
|
||||
*/
|
||||
public class PlayerClaimPlotEvent extends PlayerEvent implements Cancellable {
|
||||
private static HandlerList handlers = new HandlerList();
|
||||
private final Plot plot;
|
||||
private final boolean auto;
|
||||
private boolean cancelled;
|
||||
|
||||
/**
|
||||
* PlayerClaimPlotEvent: Called when a plot is claimed
|
||||
*
|
||||
* @param player Player that claimed the plot
|
||||
* @param plot Plot that was claimed
|
||||
*/
|
||||
public PlayerClaimPlotEvent(final Player player, final Plot plot, final boolean auto) {
|
||||
super(player);
|
||||
this.plot = plot;
|
||||
this.auto = auto;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plot involved
|
||||
*
|
||||
* @return Plot
|
||||
*/
|
||||
public Plot getPlot() {
|
||||
return plot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if it was an automated claim, else false
|
||||
*/
|
||||
public boolean wasAuto() {
|
||||
return auto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(final boolean b) {
|
||||
cancelled = b;
|
@ -0,0 +1,63 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.events;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
|
||||
/**
|
||||
|
||||
|
||||
*/
|
||||
public class PlayerEnterPlotEvent extends PlayerEvent {
|
||||
private static HandlerList handlers = new HandlerList();
|
||||
private final Plot plot;
|
||||
|
||||
/**
|
||||
* PlayerEnterPlotEvent: Called when a player leaves a plot
|
||||
*
|
||||
* @param player Player that entered the plot
|
||||
* @param plot Plot that was entered
|
||||
*/
|
||||
public PlayerEnterPlotEvent(final Player player, final Plot plot) {
|
||||
super(player);
|
||||
this.plot = plot;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plot involved
|
||||
*
|
||||
* @return Plot
|
||||
*/
|
||||
public Plot getPlot() {
|
||||
return plot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
@ -0,0 +1,64 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.events;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
|
||||
/**
|
||||
|
||||
|
||||
*/
|
||||
public class PlayerLeavePlotEvent extends PlayerEvent {
|
||||
|
||||
private static HandlerList handlers = new HandlerList();
|
||||
private final Plot plot;
|
||||
|
||||
/**
|
||||
* PlayerLeavePlotEvent: Called when a player leaves a plot
|
||||
*
|
||||
* @param player Player that left the plot
|
||||
* @param plot Plot that was left
|
||||
*/
|
||||
public PlayerLeavePlotEvent(final Player player, final Plot plot) {
|
||||
super(player);
|
||||
this.plot = plot;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plot involved
|
||||
*
|
||||
* @return Plot
|
||||
*/
|
||||
public Plot getPlot() {
|
||||
return plot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
@ -0,0 +1,89 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
|
||||
/**
|
||||
|
||||
|
||||
*/
|
||||
public class PlayerPlotDeniedEvent extends PlotEvent {
|
||||
|
||||
private static HandlerList handlers = new HandlerList();
|
||||
private final Player initiator;
|
||||
private final boolean added;
|
||||
private final UUID player;
|
||||
|
||||
/**
|
||||
* PlayerPlotDeniedEvent: Called when the denied UUID list is modified for a plot
|
||||
*
|
||||
* @param initiator Player that initiated the event
|
||||
* @param plot Plot in which the event occurred
|
||||
* @param player Player that was denied/un-denied
|
||||
* @param added true of add to deny list, false if removed
|
||||
*/
|
||||
public PlayerPlotDeniedEvent(final Player initiator, final Plot plot, final UUID player, final boolean added) {
|
||||
super(plot);
|
||||
this.initiator = initiator;
|
||||
this.added = added;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a user was added
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean wasAdded() {
|
||||
return added;
|
||||
}
|
||||
|
||||
/**
|
||||
* The player added/removed
|
||||
*
|
||||
* @return UUID
|
||||
*/
|
||||
public UUID getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* The player initiating the action
|
||||
*
|
||||
* @return Player
|
||||
*/
|
||||
public Player getInitiator() {
|
||||
return initiator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
@ -0,0 +1,89 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
|
||||
/**
|
||||
|
||||
|
||||
*/
|
||||
public class PlayerPlotHelperEvent extends PlotEvent {
|
||||
|
||||
private static HandlerList handlers = new HandlerList();
|
||||
private final Player initiator;
|
||||
private final boolean added;
|
||||
private final UUID player;
|
||||
|
||||
/**
|
||||
* PlayerPlotHelperEvent: Called when a plot helper is added/removed
|
||||
*
|
||||
* @param initiator Player that initiated the event
|
||||
* @param plot Plot in which the event occurred
|
||||
* @param player Player that was added/removed from the helper list
|
||||
* @param added true of the player was added, false if the player was removed
|
||||
*/
|
||||
public PlayerPlotHelperEvent(final Player initiator, final Plot plot, final UUID player, final boolean added) {
|
||||
super(plot);
|
||||
this.initiator = initiator;
|
||||
this.added = added;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a player was added
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean wasAdded() {
|
||||
return added;
|
||||
}
|
||||
|
||||
/**
|
||||
* The UUID added/removed
|
||||
*
|
||||
* @return UUID
|
||||
*/
|
||||
public UUID getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* The player initiating the action
|
||||
*
|
||||
* @return Player
|
||||
*/
|
||||
public Player getInitiator() {
|
||||
return initiator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
@ -0,0 +1,89 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
|
||||
/**
|
||||
|
||||
|
||||
*/
|
||||
public class PlayerPlotTrustedEvent extends PlotEvent {
|
||||
|
||||
private static HandlerList handlers = new HandlerList();
|
||||
private final Player initiator;
|
||||
private final boolean added;
|
||||
private final UUID player;
|
||||
|
||||
/**
|
||||
* PlayerPlotTrustedEvent: Called when a plot trusted user is added/removed
|
||||
*
|
||||
* @param initiator Player that initiated the event
|
||||
* @param plot Plot in which the event occurred
|
||||
* @param player Player that was added/removed from the trusted list
|
||||
* @param added true of the player was added, false if the player was removed
|
||||
*/
|
||||
public PlayerPlotTrustedEvent(final Player initiator, final Plot plot, final UUID player, final boolean added) {
|
||||
super(plot);
|
||||
this.initiator = initiator;
|
||||
this.added = added;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a player was added
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean wasAdded() {
|
||||
return added;
|
||||
}
|
||||
|
||||
/**
|
||||
* The UUID added/removed
|
||||
*
|
||||
* @return UUID
|
||||
*/
|
||||
public UUID getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* The player initiating the action
|
||||
*
|
||||
* @return Player
|
||||
*/
|
||||
public Player getInitiator() {
|
||||
return initiator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
@ -0,0 +1,90 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.events;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
|
||||
/**
|
||||
* Called when a player teleports to a plot
|
||||
*
|
||||
|
||||
|
||||
*/
|
||||
public class PlayerTeleportToPlotEvent extends PlayerEvent implements Cancellable {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private final Location from;
|
||||
private final Plot plot;
|
||||
private boolean cancelled;
|
||||
|
||||
/**
|
||||
* PlayerTeleportToPlotEvent: Called when a player teleports to a plot
|
||||
*
|
||||
* @param player That was teleported
|
||||
* @param from Start location
|
||||
* @param plot Plot to which the player was teleported
|
||||
*/
|
||||
public PlayerTeleportToPlotEvent(final Player player, final Location from, final Plot plot) {
|
||||
super(player);
|
||||
this.from = from;
|
||||
this.plot = plot;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the from location
|
||||
*
|
||||
* @return Location
|
||||
*/
|
||||
public Location getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plot involved
|
||||
*
|
||||
* @return Plot
|
||||
*/
|
||||
public Plot getPlot() {
|
||||
return plot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(final boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
@ -0,0 +1,77 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.events;
|
||||
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
|
||||
/**
|
||||
* Called when a plot is cleared
|
||||
*
|
||||
|
||||
|
||||
*/
|
||||
public class PlotClearEvent extends PlotEvent implements Cancellable {
|
||||
public PlotClearEvent(Plot plot) {
|
||||
super(plot);
|
||||
}
|
||||
|
||||
private static HandlerList handlers = new HandlerList();
|
||||
private boolean cancelled;
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PlotId
|
||||
*
|
||||
* @return PlotId
|
||||
*/
|
||||
public PlotId getPlotId() {
|
||||
return getPlot().getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the world name
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getWorld() {
|
||||
return getPlot().getArea().worldname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(final boolean b) {
|
||||
cancelled = b;
|
@ -0,0 +1,65 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.events;
|
||||
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
|
||||
/**
|
||||
* Called when a plot is deleted
|
||||
*
|
||||
|
||||
|
||||
*/
|
||||
public class PlotDeleteEvent extends PlotEvent {
|
||||
public PlotDeleteEvent(Plot plot) {
|
||||
super(plot);
|
||||
}
|
||||
|
||||
private static HandlerList handlers = new HandlerList();
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PlotId
|
||||
*
|
||||
* @return PlotId
|
||||
*/
|
||||
public PlotId getPlotId() {
|
||||
return getPlot().getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the world name
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getWorld() {
|
||||
return getPlot().getArea().worldname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
@ -0,0 +1,19 @@
|
||||
package com.plotsquared.bukkit.events;
|
||||
|
||||
import org.bukkit.event.Event;
|
||||
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
|
||||
public abstract class PlotEvent extends Event {
|
||||
|
||||
private final Plot plot;
|
||||
|
||||
public PlotEvent(final Plot plot) {
|
||||
this.plot = plot;
|
||||
}
|
||||
|
||||
public final Plot getPlot() {
|
||||
return plot;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.events;
|
||||
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.intellectualcrafters.plot.flag.Flag;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
|
||||
/**
|
||||
* Called when a Flag is added to a plot
|
||||
*
|
||||
|
||||
|
||||
*/
|
||||
public class PlotFlagAddEvent extends PlotEvent implements Cancellable {
|
||||
|
||||
private static HandlerList handlers = new HandlerList();
|
||||
private final Flag flag;
|
||||
private boolean cancelled;
|
||||
|
||||
/**
|
||||
* PlotFlagAddEvent: Called when a Flag is added to a plot
|
||||
*
|
||||
* @param flag Flag that was added
|
||||
* @param plot Plot to which the flag was added
|
||||
*/
|
||||
public PlotFlagAddEvent(final Flag flag, final Plot plot) {
|
||||
super(plot);
|
||||
this.flag = flag;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the flag involved
|
||||
*
|
||||
* @return Flag
|
||||
*/
|
||||
public Flag getFlag() {
|
||||
return flag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setCancelled(final boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
@ -0,0 +1,77 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.events;
|
||||
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.intellectualcrafters.plot.flag.Flag;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
|
||||
/**
|
||||
* Called when a flag is removed from a plot
|
||||
*
|
||||
|
||||
|
||||
*/
|
||||
public class PlotFlagRemoveEvent extends PlotEvent implements Cancellable {
|
||||
|
||||
private static HandlerList handlers = new HandlerList();
|
||||
private final Flag flag;
|
||||
private boolean cancelled;
|
||||
|
||||
/**
|
||||
* PlotFlagRemoveEvent: Called when a flag is removed from a plot
|
||||
*
|
||||
* @param flag Flag that was removed
|
||||
* @param plot Plot from which the flag was removed
|
||||
*/
|
||||
public PlotFlagRemoveEvent(final Flag flag, final Plot plot) {
|
||||
super(plot);
|
||||
this.flag = flag;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the flag involved
|
||||
*
|
||||
* @return Flag
|
||||
*/
|
||||
public Flag getFlag() {
|
||||
return flag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setCancelled(final boolean cancelled) {
|
||||
this.cancelled = cancelled;
|
@ -0,0 +1,93 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.events;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
|
||||
/**
|
||||
|
||||
*/
|
||||
public class PlotMergeEvent extends Event implements Cancellable {
|
||||
private static HandlerList handlers = new HandlerList();
|
||||
private final ArrayList<PlotId> plots;
|
||||
private boolean cancelled;
|
||||
private Plot plot;
|
||||
private World world;
|
||||
|
||||
/**
|
||||
* PlotMergeEvent: Called when plots are merged
|
||||
*
|
||||
* @param world World in which the event occurred
|
||||
* @param plot Plot that was merged
|
||||
* @param plots A list of plots involved in the event
|
||||
*/
|
||||
public PlotMergeEvent(final World world, final Plot plot, final ArrayList<PlotId> plots) {
|
||||
this.plots = plots;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plots being added;
|
||||
*
|
||||
* @return Plot
|
||||
*/
|
||||
public ArrayList<PlotId> getPlots() {
|
||||
return plots;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the main plot
|
||||
*
|
||||
* @return Plot
|
||||
*/
|
||||
public Plot getPlot() {
|
||||
return plot;
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(final boolean b) {
|
||||
cancelled = b;
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package com.plotsquared.bukkit.events;
|
||||
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.Rating;
|
||||
|
||||
/**
|
||||
* Created 2015-07-13 for PlotSquaredGit
|
||||
*
|
||||
|
||||
*/
|
||||
public class PlotRateEvent extends PlotEvent {
|
||||
|
||||
private static HandlerList handlers = new HandlerList();
|
||||
private final PlotPlayer rater;
|
||||
private Rating rating;
|
||||
|
||||
public PlotRateEvent(final PlotPlayer rater, final Rating rating, final Plot plot) {
|
||||
super(plot);
|
||||
this.rater = rater;
|
||||
this.rating = rating;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public PlotPlayer getRater() {
|
||||
return rater;
|
||||
}
|
||||
|
||||
public void setRating(final Rating rating) {
|
||||
this.rating = rating;
|
||||
}
|
||||
|
||||
public Rating getRating() {
|
||||
return rating;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
@ -0,0 +1,89 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.events;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import com.intellectualcrafters.plot.object.PlotArea;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
|
||||
/**
|
||||
|
||||
*/
|
||||
public class PlotUnlinkEvent extends Event implements Cancellable {
|
||||
private static HandlerList handlers = new HandlerList();
|
||||
private final ArrayList<PlotId> plots;
|
||||
private final World world;
|
||||
private boolean cancelled;
|
||||
private final PlotArea area;
|
||||
|
||||
/**
|
||||
* Called when a mega-plot is unlinked.
|
||||
*
|
||||
* @param world World in which the event occurred
|
||||
* @param plots Plots that are involved in the event
|
||||
*/
|
||||
public PlotUnlinkEvent(final World world, PlotArea area, final ArrayList<PlotId> plots) {
|
||||
this.plots = plots;
|
||||
this.world = world;
|
||||
this.area = area;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plots involved
|
||||
*
|
||||
* @return PlotId
|
||||
*/
|
||||
public ArrayList<PlotId> getPlots() {
|
||||
return plots;
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
public PlotArea getArea() {
|
||||
return area;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(final boolean b) {
|
||||
cancelled = b;
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.plotsquared.bukkit.generator;
|
||||
|
||||
import com.intellectualcrafters.plot.generator.AugmentedUtils;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class BukkitAugmentedGenerator extends BlockPopulator {
|
||||
|
||||
private static BukkitAugmentedGenerator generator;
|
||||
|
||||
private BukkitAugmentedGenerator() {}
|
||||
|
||||
public static BukkitAugmentedGenerator get(World world) {
|
||||
for (BlockPopulator populator : world.getPopulators()) {
|
||||
if (populator instanceof BukkitAugmentedGenerator) {
|
||||
return (BukkitAugmentedGenerator) populator;
|
||||
}
|
||||
}
|
||||
if (generator == null) {
|
||||
generator = new BukkitAugmentedGenerator();
|
||||
}
|
||||
world.getPopulators().add(generator);
|
||||
return generator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void populate(final World world, Random r, final Chunk chunk) {
|
||||
AugmentedUtils.generate(world.getName(), chunk.getX(), chunk.getZ(), null);
|
||||
}
|
||||
}
|
@ -0,0 +1,336 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.generator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.generator.GeneratorWrapper;
|
||||
import com.intellectualcrafters.plot.generator.HybridGen;
|
||||
import com.intellectualcrafters.plot.generator.IndependentPlotGenerator;
|
||||
import com.intellectualcrafters.plot.object.PlotArea;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
import com.intellectualcrafters.plot.object.PlotManager;
|
||||
import com.intellectualcrafters.plot.object.PseudoRandom;
|
||||
import com.intellectualcrafters.plot.object.SetupObject;
|
||||
import com.intellectualcrafters.plot.util.ChunkManager;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.PlotChunk;
|
||||
import com.intellectualcrafters.plot.util.SetQueue;
|
||||
import com.plotsquared.bukkit.listeners.WorldEvents;
|
||||
import com.plotsquared.bukkit.util.BukkitUtil;
|
||||
import com.plotsquared.bukkit.util.block.GenChunk;
|
||||
|
||||
public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrapper<ChunkGenerator> {
|
||||
|
||||
private final PlotChunk<Chunk> chunkSetter;
|
||||
private final PseudoRandom random = new PseudoRandom();
|
||||
private final IndependentPlotGenerator plotGenerator;
|
||||
private final List<BlockPopulator> populators = new ArrayList<>();
|
||||
private boolean loaded = false;
|
||||
private ChunkGenerator platformGenerator;
|
||||
private boolean full;
|
||||
|
||||
public BukkitPlotGenerator(IndependentPlotGenerator generator) {
|
||||
this.plotGenerator = generator;
|
||||
this.platformGenerator = this;
|
||||
populators.add(new BlockPopulator() {
|
||||
@Override
|
||||
public void populate(World world, Random r, Chunk c) {
|
||||
if (!(chunkSetter instanceof GenChunk)) {
|
||||
PS.debug("Current PlotChunk is not relevant to population?");
|
||||
PS.stacktrace();
|
||||
return;
|
||||
}
|
||||
GenChunk result = (GenChunk) chunkSetter;
|
||||
if (result.result_data != null) {
|
||||
for (int i = 0; i < result.result_data.length; i++) {
|
||||
byte[] section = result.result_data[i];
|
||||
if (section == null) {
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < section.length; j++) {
|
||||
int x = MainUtil.x_loc[i][j];
|
||||
int y = MainUtil.y_loc[i][j];
|
||||
int z = MainUtil.z_loc[i][j];
|
||||
c.getBlock(x, y, z).setData(section[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
chunkSetter = new GenChunk(null, null);
|
||||
this.full = true;
|
||||
MainUtil.initCache();
|
||||
}
|
||||
|
||||
public BukkitPlotGenerator(final String world, final ChunkGenerator cg) {
|
||||
if (cg instanceof BukkitPlotGenerator) {
|
||||
throw new IllegalArgumentException("ChunkGenerator: " + cg.getClass().getName() + " is already a BukkitPlotGenerator!");
|
||||
}
|
||||
this.full = false;
|
||||
WorldEvents.lastWorld = world;
|
||||
PS.get().debug("BukkitPlotGenerator does not fully support: " + cg);
|
||||
platformGenerator = cg;
|
||||
plotGenerator = new IndependentPlotGenerator() {
|
||||
@Override
|
||||
public void processSetup(SetupObject setup) {}
|
||||
|
||||
@Override
|
||||
public void initialize(PlotArea area) {}
|
||||
|
||||
@Override
|
||||
public PlotManager getNewPlotManager() {
|
||||
return new HybridGen().getNewPlotManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return cg.getClass().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotArea getNewPlotArea(String world, String id, PlotId min, PlotId max) {
|
||||
return new HybridGen().getNewPlotArea(world, id, min, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateChunk(final PlotChunk<?> result, final PlotArea settings, final PseudoRandom random) {
|
||||
World w = BukkitUtil.getWorld(world);
|
||||
Random r = new Random(result.getChunkWrapper().hashCode());
|
||||
BiomeGrid grid = new BiomeGrid() {
|
||||
@Override
|
||||
public void setBiome(int x, int z, Biome biome) {
|
||||
result.setBiome(x, z, biome.ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Biome getBiome(int arg0, int arg1) {
|
||||
return Biome.FOREST;
|
||||
}
|
||||
};
|
||||
try {
|
||||
// ChunkData will spill a bit
|
||||
ChunkData data = cg.generateChunkData(w, r, result.getX(), result.getZ(), grid);
|
||||
if (data != null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {}
|
||||
// Populator spillage
|
||||
short[][] tmp = cg.generateExtBlockSections(w, r, result.getX(), result.getZ(), grid);
|
||||
if (tmp != null) {
|
||||
for (int i = 0; i < tmp.length; i++) {
|
||||
short[] section = tmp[i];
|
||||
if (section == null) {
|
||||
if (i < 7) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int y = i << 4; y < (i << 4) + 16; y++) {
|
||||
result.setBlock(x, y, z, (short) 0, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < section.length; j++) {
|
||||
int x = MainUtil.x_loc[i][j];
|
||||
int y = MainUtil.y_loc[i][j];
|
||||
int z = MainUtil.z_loc[i][j];
|
||||
result.setBlock(x, y, z, section[j], (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (BlockPopulator populator : cg.getDefaultPopulators(w)) {
|
||||
populator.populate(w, r, (Chunk) result.getChunk());
|
||||
}
|
||||
}
|
||||
};
|
||||
chunkSetter = new GenChunk(null, SetQueue.IMP.new ChunkWrapper(world, 0, 0));
|
||||
if (cg != null) {
|
||||
populators.addAll(cg.getDefaultPopulators(BukkitUtil.getWorld(world)));
|
||||
}
|
||||
MainUtil.initCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void augment(PlotArea area) {
|
||||
BukkitAugmentedGenerator.get(BukkitUtil.getWorld(area.worldname));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFull() {
|
||||
return full;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndependentPlotGenerator getPlotGenerator() {
|
||||
return plotGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkGenerator getPlatformGenerator() {
|
||||
return platformGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockPopulator> getDefaultPopulators(final World world) {
|
||||
try {
|
||||
if (!loaded) {
|
||||
final String name = WorldEvents.getName(world);
|
||||
PS.get().loadWorld(name, this);
|
||||
Set<PlotArea> areas = PS.get().getPlotAreas(name);
|
||||
if (!areas.isEmpty()) {
|
||||
PlotArea area = areas.iterator().next();
|
||||
if (!area.MOB_SPAWNING) {
|
||||
if (!area.SPAWN_EGGS) {
|
||||
world.setSpawnFlags(false, false);
|
||||
}
|
||||
world.setAmbientSpawnLimit(0);
|
||||
world.setAnimalSpawnLimit(0);
|
||||
world.setMonsterSpawnLimit(0);
|
||||
world.setWaterAnimalSpawnLimit(0);
|
||||
} else {
|
||||
world.setSpawnFlags(true, true);
|
||||
world.setAmbientSpawnLimit(-1);
|
||||
world.setAnimalSpawnLimit(-1);
|
||||
world.setMonsterSpawnLimit(-1);
|
||||
world.setWaterAnimalSpawnLimit(-1);
|
||||
}
|
||||
}
|
||||
loaded = true;
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return populators;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkData generateChunkData(World world, Random random, int cx, int cz, BiomeGrid grid) {
|
||||
if (!(chunkSetter instanceof GenChunk)) {
|
||||
PS.debug("Current PlotChunk is not relevant to generation?");
|
||||
PS.stacktrace();
|
||||
return null;
|
||||
}
|
||||
GenChunk result = (GenChunk) chunkSetter;
|
||||
// Set the chunk location
|
||||
result.setChunkWrapper(SetQueue.IMP.new ChunkWrapper(world.getName(), cx, cz));
|
||||
// Set the result data
|
||||
result.cd = createChunkData(world);
|
||||
result.grid = grid;
|
||||
// Catch any exceptions (as exceptions usually thrown
|
||||
try {
|
||||
// Fill the result data if necessary
|
||||
if (platformGenerator != this) {
|
||||
return platformGenerator.generateChunkData(world, random, cx, cz, grid);
|
||||
} else {
|
||||
generate(world, cx, cz, result);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// Return the result data
|
||||
return result.cd;
|
||||
}
|
||||
|
||||
public void generate(World world, int cx, int cz, GenChunk result) {
|
||||
// Load if improperly loaded
|
||||
if (!loaded) {
|
||||
final String name = WorldEvents.getName(world);
|
||||
PS.get().loadWorld(name, this);
|
||||
loaded = true;
|
||||
}
|
||||
// Set random seed
|
||||
this.random.state = (cx << 16) | (cz & 0xFFFF);
|
||||
// Process the chunk
|
||||
result.modified = false;
|
||||
ChunkManager.preProcessChunk(result);
|
||||
if (result.modified) {
|
||||
return;
|
||||
}
|
||||
PlotArea area = PS.get().getPlotArea(world.getName(), null);
|
||||
plotGenerator.generateChunk(chunkSetter, area, this.random);
|
||||
ChunkManager.postProcessChunk(result);
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short[][] generateExtBlockSections(final World world, final Random r, final int cx, final int cz, final BiomeGrid grid) {
|
||||
if (!(chunkSetter instanceof GenChunk)) {
|
||||
PS.stacktrace();
|
||||
return new short[16][];
|
||||
}
|
||||
GenChunk result = (GenChunk) chunkSetter;
|
||||
// Set the chunk location
|
||||
result.setChunkWrapper(SetQueue.IMP.new ChunkWrapper(world.getName(), cx, cz));
|
||||
// Set the result data
|
||||
result.result = new short[16][];
|
||||
result.result_data = new byte[16][];
|
||||
// Catch any exceptions (as exceptions usually thrown
|
||||
try {
|
||||
// Fill the result data
|
||||
if (platformGenerator != this) {
|
||||
return platformGenerator.generateExtBlockSections(world, r, cx, cz, grid);
|
||||
} else {
|
||||
generate(world, cx, cz, result);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// Return the result data
|
||||
return result.result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow spawning everywhere
|
||||
*/
|
||||
@Override
|
||||
public boolean canSpawn(final World world, final int x, final int z) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (platformGenerator == this) {
|
||||
return "" + plotGenerator;
|
||||
}
|
||||
return platformGenerator == null ? "null" : platformGenerator.getClass().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
return (toString().equals(obj.toString()) || toString().equals(obj.getClass().getName()));
|
||||
}
|
||||
}
|
@ -0,0 +1,326 @@
|
||||
package com.plotsquared.bukkit.listeners;
|
||||
|
||||
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
|
||||
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.config.Settings;
|
||||
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.RefField;
|
||||
import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandler;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.entity.ItemSpawnEvent;
|
||||
import org.bukkit.event.world.ChunkLoadEvent;
|
||||
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class ChunkListener implements Listener {
|
||||
|
||||
private final RefClass classChunk = getRefClass("{nms}.Chunk");
|
||||
private final RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
|
||||
private final RefField mustSave = classChunk.getField("mustSave");
|
||||
private Chunk lastChunk = null;
|
||||
private RefMethod methodGetHandleChunk;
|
||||
|
||||
|
||||
public ChunkListener() {
|
||||
RefMethod method;
|
||||
try {
|
||||
method = classCraftChunk.getMethod("getHandle");
|
||||
} catch (final Exception e) {
|
||||
method = null;
|
||||
e.printStackTrace();
|
||||
}
|
||||
methodGetHandleChunk = method;
|
||||
|
||||
if (!Settings.CHUNK_PROCESSOR_GC) {
|
||||
return;
|
||||
}
|
||||
TaskManager.runTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final int distance = Bukkit.getViewDistance() + 2;
|
||||
final HashMap<String, HashMap<ChunkLoc, Integer>> players = new HashMap<>();
|
||||
for (final Entry<String, PlotPlayer> entry : UUIDHandler.getPlayers().entrySet()) {
|
||||
final PlotPlayer pp = entry.getValue();
|
||||
final Location loc = pp.getLocation();
|
||||
final String world = loc.getWorld();
|
||||
if (!PS.get().hasPlotArea(world)) {
|
||||
continue;
|
||||
}
|
||||
HashMap<ChunkLoc, Integer> map = players.get(world);
|
||||
if (map == null) {
|
||||
map = new HashMap<>();
|
||||
players.put(world, map);
|
||||
}
|
||||
final ChunkLoc origin = new ChunkLoc(loc.getX() >> 4, loc.getZ() >> 4);
|
||||
Integer val = map.get(origin);
|
||||
int check;
|
||||
if (val != null) {
|
||||
if (val == distance) {
|
||||
continue;
|
||||
}
|
||||
check = distance - val;
|
||||
} else {
|
||||
check = distance;
|
||||
map.put(origin, distance);
|
||||
}
|
||||
for (int x = -distance; x <= distance; x++) {
|
||||
if (x >= check || -x >= check) {
|
||||
continue;
|
||||
}
|
||||
for (int z = -distance; z <= distance; z++) {
|
||||
if (z >= check || -z >= check) {
|
||||
continue;
|
||||
}
|
||||
final int weight = distance - Math.max(Math.abs(x), Math.abs(z));
|
||||
final ChunkLoc chunk = new ChunkLoc(x + origin.x, z + origin.z);
|
||||
val = map.get(chunk);
|
||||
if (val == null || val < weight) {
|
||||
map.put(chunk, weight);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
int time = 300;
|
||||
for (final World world : Bukkit.getWorlds()) {
|
||||
final String name = world.getName();
|
||||
if (!PS.get().hasPlotArea(name)) {
|
||||
continue;
|
||||
}
|
||||
final boolean autosave = world.isAutoSave();
|
||||
if (autosave) {
|
||||
world.setAutoSave(false);
|
||||
}
|
||||
final HashMap<ChunkLoc, Integer> map = players.get(name);
|
||||
if (map == null || map.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
Chunk[] chunks = world.getLoadedChunks();
|
||||
ArrayDeque<Chunk> toUnload = new ArrayDeque<>();
|
||||
for (final Chunk chunk : chunks) {
|
||||
final int x = chunk.getX();
|
||||
final int z = chunk.getZ();
|
||||
if (!map.containsKey(new ChunkLoc(x, z))) {
|
||||
toUnload.add(chunk);
|
||||
}
|
||||
}
|
||||
if (!toUnload.isEmpty()) {
|
||||
long start = System.currentTimeMillis();
|
||||
Chunk chunk;
|
||||
while ((chunk = toUnload.poll()) != null && System.currentTimeMillis() - start < 5) {
|
||||
if (!Settings.CHUNK_PROCESSOR_TRIM_ON_SAVE || !unloadChunk(name, chunk)) {
|
||||
if (chunk.isLoaded()) {
|
||||
chunk.unload(true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!toUnload.isEmpty()) {
|
||||
time = 1;
|
||||
}
|
||||
}
|
||||
if (!Settings.CHUNK_PROCESSOR_TRIM_ON_SAVE && autosave) {
|
||||
world.setAutoSave(true);
|
||||
}
|
||||
}
|
||||
TaskManager.runTaskLater(this, time);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public boolean unloadChunk(final String world, final Chunk chunk) {
|
||||
final int X = chunk.getX();
|
||||
final int Z = chunk.getZ();
|
||||
final int x = X << 4;
|
||||
final int z = Z << 4;
|
||||
final int x2 = x + 15;
|
||||
final int z2 = z + 15;
|
||||
Thread thread = new Thread();
|
||||
Plot plot = new Location(world, x, 1, z).getOwnedPlotAbs();
|
||||
if (plot != null && plot.hasOwner()) {
|
||||
return false;
|
||||
}
|
||||
plot = new Location(world, x2, 1, z2).getOwnedPlotAbs();
|
||||
if (plot != null && plot.hasOwner()) {
|
||||
return false;
|
||||
}
|
||||
plot = new Location(world, x2, 1, z).getOwnedPlotAbs();
|
||||
if (plot != null && plot.hasOwner()) {
|
||||
return false;
|
||||
}
|
||||
plot = new Location(world, x, 1, z2).getOwnedPlotAbs();
|
||||
if (plot != null && plot.hasOwner()) {
|
||||
return false;
|
||||
}
|
||||
plot = new Location(world, x + 7, 1, z + 7).getOwnedPlotAbs();
|
||||
if (plot != null && plot.hasOwner()) {
|
||||
return false;
|
||||
}
|
||||
final Object c = methodGetHandleChunk.of(chunk).call();
|
||||
mustSave.of(c).set(false);
|
||||
if (chunk.isLoaded()) {
|
||||
chunk.unload(false, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onChunkUnload(final ChunkUnloadEvent event) {
|
||||
if (Settings.CHUNK_PROCESSOR_TRIM_ON_SAVE) {
|
||||
final Chunk chunk = event.getChunk();
|
||||
final String world = chunk.getWorld().getName();
|
||||
if (PS.get().hasPlotArea(world)) {
|
||||
if (unloadChunk(world, chunk)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (processChunk(event.getChunk(), true)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onChunkLoad(final ChunkLoadEvent event) {
|
||||
processChunk(event.getChunk(), false);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onItemSpawn(final ItemSpawnEvent event) {
|
||||
final Item entity = event.getEntity();
|
||||
final Chunk chunk = entity.getLocation().getChunk();
|
||||
if (chunk == lastChunk) {
|
||||
event.getEntity().remove();
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if (!PS.get().hasPlotArea(chunk.getWorld().getName())) {
|
||||
return;
|
||||
}
|
||||
final Entity[] entities = chunk.getEntities();
|
||||
if (entities.length > Settings.CHUNK_PROCESSOR_MAX_ENTITIES) {
|
||||
event.getEntity().remove();
|
||||
event.setCancelled(true);
|
||||
lastChunk = chunk;
|
||||
} else {
|
||||
lastChunk = null;
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onBlockPhysics(final BlockPhysicsEvent event) {
|
||||
if (Settings.CHUNK_PROCESSOR_DISABLE_PHYSICS) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onEntitySpawn(final CreatureSpawnEvent event) {
|
||||
final LivingEntity entity = event.getEntity();
|
||||
final Chunk chunk = entity.getLocation().getChunk();
|
||||
if (chunk == lastChunk) {
|
||||
event.getEntity().remove();
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if (!PS.get().hasPlotArea(chunk.getWorld().getName())) {
|
||||
return;
|
||||
}
|
||||
final Entity[] entities = chunk.getEntities();
|
||||
if (entities.length > Settings.CHUNK_PROCESSOR_MAX_ENTITIES) {
|
||||
event.getEntity().remove();
|
||||
event.setCancelled(true);
|
||||
lastChunk = chunk;
|
||||
} else {
|
||||
lastChunk = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanChunk(final Chunk chunk) {
|
||||
TaskManager.index.incrementAndGet();
|
||||
final Integer currentIndex = TaskManager.index.get();
|
||||
final Integer task = TaskManager.runTaskRepeat(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!chunk.isLoaded()) {
|
||||
Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex));
|
||||
TaskManager.tasks.remove(currentIndex);
|
||||
PS.debug("[PlotSquared] &aSuccessfully processed and unloaded chunk!");
|
||||
chunk.unload(true, true);
|
||||
return;
|
||||
}
|
||||
final BlockState[] tiles = chunk.getTileEntities();
|
||||
if (tiles.length == 0) {
|
||||
Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex));
|
||||
TaskManager.tasks.remove(currentIndex);
|
||||
PS.debug("[PlotSquared] &aSuccessfully processed and unloaded chunk!");
|
||||
chunk.unload(true, true);
|
||||
return;
|
||||
}
|
||||
final long start = System.currentTimeMillis();
|
||||
int i = 0;
|
||||
while (System.currentTimeMillis() - start < 250) {
|
||||
if (i >= tiles.length) {
|
||||
Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex));
|
||||
TaskManager.tasks.remove(currentIndex);
|
||||
PS.debug("[PlotSquared] &aSuccessfully processed and unloaded chunk!");
|
||||
chunk.unload(true, true);
|
||||
return;
|
||||
}
|
||||
tiles[i].getBlock().setType(Material.AIR, false);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}, 5);
|
||||
TaskManager.tasks.put(currentIndex, task);
|
||||
}
|
||||
|
||||
public boolean processChunk(final Chunk chunk, final boolean unload) {
|
||||
if (!PS.get().hasPlotArea(chunk.getWorld().getName())) {
|
||||
return false;
|
||||
}
|
||||
final Entity[] entities = chunk.getEntities();
|
||||
final BlockState[] tiles = chunk.getTileEntities();
|
||||
if (entities.length > Settings.CHUNK_PROCESSOR_MAX_ENTITIES) {
|
||||
for (final Entity ent : entities) {
|
||||
if (!(ent instanceof Player)) {
|
||||
ent.remove();
|
||||
}
|
||||
}
|
||||
PS.debug("[PlotSquared] &a detected unsafe chunk and processed: " + (chunk.getX() << 4) + "," + (chunk.getX() << 4));
|
||||
}
|
||||
if (tiles.length > Settings.CHUNK_PROCESSOR_MAX_BLOCKSTATES) {
|
||||
if (unload) {
|
||||
PS.debug("[PlotSquared] &c detected unsafe chunk: " + (chunk.getX() << 4) + "," + (chunk.getX() << 4));
|
||||
cleanChunk(chunk);
|
||||
return true;
|
||||
}
|
||||
for (final BlockState tile : tiles) {
|
||||
tile.getBlock().setType(Material.AIR, false);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.listeners;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import com.intellectualcrafters.plot.flag.FlagManager;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.plotsquared.bukkit.events.PlayerEnterPlotEvent;
|
||||
import com.plotsquared.bukkit.object.BukkitPlayer;
|
||||
import com.plotsquared.bukkit.util.BukkitUtil;
|
||||
|
||||
/**
|
||||
|
||||
*/
|
||||
public class ForceFieldListener implements Listener {
|
||||
private Set<PlotPlayer> getNearbyPlayers(final Player player, final Plot plot) {
|
||||
final Set<PlotPlayer> players = new HashSet<>();
|
||||
PlotPlayer pp;
|
||||
for (final Entity entity : player.getNearbyEntities(5d, 5d, 5d)) {
|
||||
if (!(entity instanceof Player) || ((pp = BukkitUtil.getPlayer((Player) entity)) == null) || !plot.equals(pp.getCurrentPlot())) {
|
||||
continue;
|
||||
}
|
||||
if (!plot.isAdded(pp.getUUID())) {
|
||||
players.add(pp);
|
||||
}
|
||||
}
|
||||
return players;
|
||||
}
|
||||
|
||||
private PlotPlayer hasNearbyPermitted(final Player player, final Plot plot) {
|
||||
PlotPlayer pp;
|
||||
for (final Entity entity : player.getNearbyEntities(5d, 5d, 5d)) {
|
||||
if (!(entity instanceof Player) || ((pp = BukkitUtil.getPlayer((Player) entity)) == null) || !plot.equals(pp.getCurrentPlot())) {
|
||||
continue;
|
||||
}
|
||||
if (plot.isAdded(pp.getUUID())) {
|
||||
return pp;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Vector calculateVelocity(final PlotPlayer pp, final PlotPlayer e) {
|
||||
Location playerLocation = pp.getLocationFull();
|
||||
Location oPlayerLocation = e.getLocation();
|
||||
final double playerX = playerLocation.getX(), playerY = playerLocation.getY(), playerZ = playerLocation.getZ(), oPlayerX = oPlayerLocation.getX(), oPlayerY = oPlayerLocation.getY(), oPlayerZ = oPlayerLocation
|
||||
.getZ();
|
||||
double x = 0d, y = 0d, z = 0d;
|
||||
if (playerX < oPlayerX) {
|
||||
x = 1.0d;
|
||||
} else if (playerX > oPlayerX) {
|
||||
x = -1.0d;
|
||||
}
|
||||
if (playerY < oPlayerY) {
|
||||
y = 0.5d;
|
||||
} else if (playerY > oPlayerY) {
|
||||
y = -0.5d;
|
||||
}
|
||||
if (playerZ < oPlayerZ) {
|
||||
z = 1.0d;
|
||||
} else if (playerZ > oPlayerZ) {
|
||||
z = -1.0d;
|
||||
}
|
||||
return new Vector(x, y, z);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlotEntry(final PlayerEnterPlotEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final PlotPlayer pp = BukkitUtil.getPlayer(player);
|
||||
final Plot plot = event.getPlot();
|
||||
if (plot == null) {
|
||||
return;
|
||||
}
|
||||
if ((FlagManager.getPlotFlagRaw(plot, "forcefield") != null) && FlagManager.getPlotFlagRaw(plot, "forcefield").getValue().equals("true")) {
|
||||
if (!FlagManager.isBooleanFlag(plot, "forcefield", false)) {
|
||||
final UUID uuid = pp.getUUID();
|
||||
if (plot.isAdded(uuid)) {
|
||||
final Set<PlotPlayer> players = getNearbyPlayers(player, plot);
|
||||
for (final PlotPlayer oPlayer : players) {
|
||||
((BukkitPlayer) oPlayer).player.setVelocity(calculateVelocity(pp, oPlayer));
|
||||
}
|
||||
} else {
|
||||
final PlotPlayer oPlayer = hasNearbyPermitted(player, plot);
|
||||
if (oPlayer == null) {
|
||||
return;
|
||||
}
|
||||
player.setVelocity(calculateVelocity(oPlayer, pp));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,155 @@
|
||||
package com.plotsquared.bukkit.listeners;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryAction;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.config.C;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotArea;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.Permissions;
|
||||
import com.plotsquared.bukkit.util.BukkitUtil;
|
||||
import com.plotsquared.listener.PlotListener;
|
||||
|
||||
public class PlayerEvents_1_8 extends PlotListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onInventoryClick(final InventoryClickEvent event) {
|
||||
if (!event.isLeftClick() || (event.getAction() != InventoryAction.PLACE_ALL) || event.isShiftClick()) {
|
||||
return;
|
||||
}
|
||||
final HumanEntity entity = event.getWhoClicked();
|
||||
if (!(entity instanceof Player) || !PS.get().hasPlotArea(entity.getWorld().getName())) {
|
||||
return;
|
||||
}
|
||||
final Player player = (Player) entity;
|
||||
final PlayerInventory inv = player.getInventory();
|
||||
final int slot = inv.getHeldItemSlot();
|
||||
if ((slot != event.getSlot()) || (slot > 8) || !event.getEventName().equals("InventoryCreativeEvent")) {
|
||||
return;
|
||||
}
|
||||
final ItemStack current = inv.getItemInHand();
|
||||
final ItemStack newItem = event.getCursor();
|
||||
final ItemMeta newMeta = newItem.getItemMeta();
|
||||
final ItemMeta oldMeta = newItem.getItemMeta();
|
||||
String newLore = "";
|
||||
if (newMeta != null) {
|
||||
final List<String> lore = newMeta.getLore();
|
||||
if (lore != null) {
|
||||
newLore = lore.toString();
|
||||
}
|
||||
}
|
||||
String oldLore = "";
|
||||
if (oldMeta != null) {
|
||||
final List<String> lore = oldMeta.getLore();
|
||||
if (lore != null) {
|
||||
oldLore = lore.toString();
|
||||
}
|
||||
}
|
||||
if (!newLore.equals("[(+NBT)]") || (current.equals(newItem) && newLore.equals(oldLore))) {
|
||||
return;
|
||||
}
|
||||
final HashSet<Byte> blocks = null;
|
||||
final Block block = player.getTargetBlock(blocks, 7);
|
||||
final BlockState state = block.getState();
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
if (state.getType() != newItem.getType()) {
|
||||
return;
|
||||
}
|
||||
final Location l = BukkitUtil.getLocation(state.getLocation());
|
||||
PlotArea area = l.getPlotArea();
|
||||
if (area == null) {
|
||||
return;
|
||||
}
|
||||
final Plot plot = area.getPlotAbs(l);
|
||||
final PlotPlayer pp = BukkitUtil.getPlayer(player);
|
||||
boolean cancelled = false;
|
||||
if (plot == null) {
|
||||
if (!Permissions.hasPermission(pp, "plots.admin.interact.road")) {
|
||||
MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.road");
|
||||
cancelled = true;
|
||||
}
|
||||
} else {
|
||||
if (!plot.hasOwner()) {
|
||||
if (!Permissions.hasPermission(pp, "plots.admin.interact.unowned")) {
|
||||
MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.unowned");
|
||||
cancelled = true;
|
||||
}
|
||||
} else {
|
||||
final UUID uuid = pp.getUUID();
|
||||
if (!plot.isAdded(uuid)) {
|
||||
if (!Permissions.hasPermission(pp, "plots.admin.interact.other")) {
|
||||
MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.other");
|
||||
cancelled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cancelled) {
|
||||
if ((current.getTypeId() == newItem.getTypeId()) && (current.getDurability() == newItem.getDurability())) {
|
||||
event.setCursor(new ItemStack(newItem.getTypeId(), newItem.getAmount(), newItem.getDurability()));
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
event.setCursor(new ItemStack(newItem.getTypeId(), newItem.getAmount(), newItem.getDurability()));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onInteract(final PlayerInteractAtEntityEvent e) {
|
||||
final Entity entity = e.getRightClicked();
|
||||
if (!(entity instanceof ArmorStand)) {
|
||||
return;
|
||||
}
|
||||
final Location l = BukkitUtil.getLocation(e.getRightClicked().getLocation());
|
||||
final PlotArea area = l.getPlotArea();
|
||||
if (area == null) {
|
||||
return;
|
||||
}
|
||||
final Plot plot = area.getPlotAbs(l);
|
||||
final PlotPlayer pp = BukkitUtil.getPlayer(e.getPlayer());
|
||||
if (plot == null) {
|
||||
if (!Permissions.hasPermission(pp, "plots.admin.interact.road")) {
|
||||
MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.road");
|
||||
e.setCancelled(true);
|
||||
}
|
||||
} else {
|
||||
if (!plot.hasOwner()) {
|
||||
if (!Permissions.hasPermission(pp, "plots.admin.interact.unowned")) {
|
||||
MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.unowned");
|
||||
e.setCancelled(true);
|
||||
}
|
||||
} else {
|
||||
final UUID uuid = pp.getUUID();
|
||||
if (!plot.isAdded(uuid)) {
|
||||
if (!Permissions.hasPermission(pp, "plots.admin.interact.other")) {
|
||||
MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, "plots.admin.interact.other");
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package com.plotsquared.bukkit.listeners;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockExplodeEvent;
|
||||
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.flag.FlagManager;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotArea;
|
||||
import com.plotsquared.bukkit.util.BukkitUtil;
|
||||
|
||||
public class PlayerEvents_1_8_3 implements Listener {
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void onBigBoom(final BlockExplodeEvent event) {
|
||||
final Block block = event.getBlock();
|
||||
Location loc = BukkitUtil.getLocation(block.getLocation());
|
||||
final String world = loc.getWorld();
|
||||
if (!PS.get().hasPlotArea(world)) {
|
||||
return;
|
||||
}
|
||||
PlotArea area = loc.getPlotArea();
|
||||
if (area == null) {
|
||||
final Iterator<Block> iter = event.blockList().iterator();
|
||||
while (iter.hasNext()) {
|
||||
loc = BukkitUtil.getLocation(iter.next().getLocation());
|
||||
if (loc.getPlotArea() != null) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
Plot plot = area.getOwnedPlot(loc);
|
||||
if (plot == null) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
if (FlagManager.isPlotFlagTrue(plot, "explosion")) {
|
||||
final Iterator<Block> iter = event.blockList().iterator();
|
||||
while (iter.hasNext()) {
|
||||
final Block b = iter.next();
|
||||
if (!plot.equals(BukkitUtil.getLocation(b.getLocation()).getPlotAbs())) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,251 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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.listeners;
|
||||
|
||||
import com.intellectualcrafters.plot.flag.Flag;
|
||||
import com.intellectualcrafters.plot.flag.FlagManager;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.plotsquared.bukkit.events.PlayerEnterPlotEvent;
|
||||
import com.plotsquared.bukkit.events.PlayerLeavePlotEvent;
|
||||
import com.plotsquared.bukkit.util.BukkitUtil;
|
||||
import com.plotsquared.listener.PlotListener;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockDamageEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
import org.bukkit.event.player.PlayerPickupItemEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created 2014-10-30 for PlotSquared
|
||||
*
|
||||
|
||||
*/
|
||||
@SuppressWarnings({ "deprecation" })
|
||||
public class PlotPlusListener extends PlotListener implements Listener {
|
||||
private final static HashMap<String, Interval> feedRunnable = new HashMap<>();
|
||||
private final static HashMap<String, Interval> healRunnable = new HashMap<>();
|
||||
|
||||
public static void startRunnable(final JavaPlugin plugin) {
|
||||
plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!healRunnable.isEmpty()) {
|
||||
for (final Iterator<Entry<String, Interval>> iter = healRunnable.entrySet().iterator(); iter.hasNext();) {
|
||||
final Entry<String, Interval> entry = iter.next();
|
||||
final Interval value = entry.getValue();
|
||||
++value.count;
|
||||
if (value.count == value.interval) {
|
||||
value.count = 0;
|
||||
final Player player = Bukkit.getPlayer(entry.getKey());
|
||||
if (player == null) {
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
final double level = player.getHealth();
|
||||
if (level != value.max) {
|
||||
player.setHealth(Math.min(level + value.amount, value.max));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!feedRunnable.isEmpty()) {
|
||||
for (final Iterator<Entry<String, Interval>> iter = feedRunnable.entrySet().iterator(); iter.hasNext();) {
|
||||
final Entry<String, Interval> entry = iter.next();
|
||||
final Interval value = entry.getValue();
|
||||
++value.count;
|
||||
if (value.count == value.interval) {
|
||||
value.count = 0;
|
||||
final Player player = Bukkit.getPlayer(entry.getKey());
|
||||
if (player == null) {
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
final int level = player.getFoodLevel();
|
||||
if (level != value.max) {
|
||||
player.setFoodLevel(Math.min(level + value.amount, value.max));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 0l, 20l);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onInteract(final BlockDamageEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
if (player.getGameMode() != GameMode.SURVIVAL) {
|
||||
return;
|
||||
}
|
||||
final Plot plot = BukkitUtil.getLocation(player).getOwnedPlot();
|
||||
if (plot == null) {
|
||||
return;
|
||||
}
|
||||
if (FlagManager.isBooleanFlag(plot, "instabreak", false)) {
|
||||
event.getBlock().breakNaturally();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onDamage(final EntityDamageEvent event) {
|
||||
if (event.getEntityType() != EntityType.PLAYER) {
|
||||
return;
|
||||
}
|
||||
final Player player = (Player) event.getEntity();
|
||||
final Plot plot = BukkitUtil.getLocation(player).getOwnedPlot();
|
||||
if (plot == null) {
|
||||
return;
|
||||
}
|
||||
if (FlagManager.isBooleanFlag(plot, "invincible", false)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onItemPickup(final PlayerPickupItemEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final PlotPlayer pp = BukkitUtil.getPlayer(player);
|
||||
final Plot plot = BukkitUtil.getLocation(player).getOwnedPlot();
|
||||
if (plot == null) {
|
||||
return;
|
||||
}
|
||||
final UUID uuid = pp.getUUID();
|
||||
if (plot.isAdded(uuid) && FlagManager.isBooleanFlag(plot, "drop-protection", false)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onItemDrop(final PlayerDropItemEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final PlotPlayer pp = BukkitUtil.getPlayer(player);
|
||||
final Plot plot = BukkitUtil.getLocation(player).getOwnedPlot();
|
||||
if (plot == null) {
|
||||
return;
|
||||
}
|
||||
final UUID uuid = pp.getUUID();
|
||||
if (plot.isAdded(uuid) && FlagManager.isBooleanFlag(plot, "item-drop", false)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlotEnter(final PlayerEnterPlotEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final Plot plot = event.getPlot();
|
||||
final Flag feed = FlagManager.getPlotFlagRaw(plot, "feed");
|
||||
if (feed != null) {
|
||||
final Integer[] value = (Integer[]) feed.getValue();
|
||||
feedRunnable.put(player.getName(), new Interval(value[0], value[1], 20));
|
||||
}
|
||||
final Flag heal = FlagManager.getPlotFlagRaw(plot, "heal");
|
||||
if (heal != null) {
|
||||
final Integer[] value = (Integer[]) heal.getValue();
|
||||
healRunnable.put(player.getName(), new Interval(value[0], value[1], 20));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerQuit(final PlayerQuitEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final String name = player.getName();
|
||||
feedRunnable.remove(name);
|
||||
healRunnable.remove(name);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlotLeave(final PlayerLeavePlotEvent event) {
|
||||
final Player leaver = event.getPlayer();
|
||||
final Plot plot = event.getPlot();
|
||||
if (!plot.hasOwner()) {
|
||||
return;
|
||||
}
|
||||
BukkitUtil.getPlayer(leaver);
|
||||
final String name = leaver.getName();
|
||||
feedRunnable.remove(name);
|
||||
healRunnable.remove(name);
|
||||
}
|
||||
|
||||
public static class Interval {
|
||||
public final int interval;
|
||||
public final int amount;
|
||||
public final int max;
|
||||
public int count = 0;
|
||||
|
||||
public Interval(final int interval, final int amount, final int max) {
|
||||
this.interval = interval;
|
||||
this.amount = amount;
|
||||
this.max = max;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Record Meta Class
|
||||
*
|
||||
|
||||
*/
|
||||
public static class RecordMeta {
|
||||
public final static List<RecordMeta> metaList = new ArrayList<>();
|
||||
static {
|
||||
for (int x = 3; x < 12; x++) {
|
||||
metaList.add(new RecordMeta(x + "", Material.valueOf("RECORD_" + x)));
|
||||
}
|
||||
}
|
||||
private final String name;
|
||||
private final Material material;
|
||||
|
||||
public RecordMeta(final String name, final Material material) {
|
||||
this.name = name;
|
||||
this.material = material;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode();
|
||||
}
|
||||
|
||||
public Material getMaterial() {
|
||||
return material;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.plotsquared.bukkit.listeners;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.WorldInitEvent;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.generator.GeneratorWrapper;
|
||||
import com.plotsquared.bukkit.generator.BukkitPlotGenerator;
|
||||
|
||||
public class WorldEvents implements Listener {
|
||||
|
||||
public static String lastWorld = null;
|
||||
|
||||
public static String getName(final World world) {
|
||||
if ((lastWorld != null) && !lastWorld.equals("CheckingPlotSquaredGenerator")) {
|
||||
return lastWorld;
|
||||
} else {
|
||||
return world.getName();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public static void onWorldInit(final WorldInitEvent event) {
|
||||
final World world = event.getWorld();
|
||||
final String name = getName(world);
|
||||
final ChunkGenerator gen = world.getGenerator();
|
||||
if (gen instanceof GeneratorWrapper) {
|
||||
PS.get().loadWorld(name, (GeneratorWrapper<?>) gen);
|
||||
} else {
|
||||
if (PS.get().config.contains("worlds." + name)) {
|
||||
PS.get().loadWorld(name, new BukkitPlotGenerator(name, gen));
|
||||
}
|
||||
}
|
||||
lastWorld = null;
|
||||
}
|
||||
}
|
@ -0,0 +1,337 @@
|
||||
package com.plotsquared.bukkit.listeners.worldedit;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.config.C;
|
||||
import com.intellectualcrafters.plot.config.Settings;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.RegionWrapper;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.Permissions;
|
||||
import com.intellectualcrafters.plot.util.SetQueue;
|
||||
import com.plotsquared.bukkit.BukkitMain;
|
||||
import com.plotsquared.bukkit.util.BukkitUtil;
|
||||
import com.plotsquared.listener.WEManager;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.bukkit.selections.Selection;
|
||||
|
||||
public class WEListener implements Listener {
|
||||
|
||||
public final HashSet<String> rad1 = new HashSet<>(Arrays.asList("forestgen", "pumpkins", "drain", "fixwater", "fixlava", "replacenear", "snow", "thaw", "ex", "butcher", "size"));
|
||||
public final HashSet<String> rad2 = new HashSet<>(Arrays.asList("fill", "fillr", "removenear", "remove"));
|
||||
public final HashSet<String> rad2_1 = new HashSet<>(Arrays.asList("hcyl", "cyl"));
|
||||
public final HashSet<String> rad2_2 = new HashSet<>(Arrays.asList("sphere", "pyramid"));
|
||||
public final HashSet<String> rad2_3 = new HashSet<>(Collections.singletonList("brush smooth"));
|
||||
public final HashSet<String> rad3_1 = new HashSet<>(Collections.singletonList("brush gravity"));
|
||||
public final HashSet<String> rad3_2 = new HashSet<>(Arrays.asList("brush sphere", "brush cylinder"));
|
||||
|
||||
public final HashSet<String> region = new HashSet<>(Arrays.asList("move", "set", "replace", "overlay", "walls", "outline", "deform", "hollow", "smooth", "naturalize", "paste", "count", "distr",
|
||||
"regen", "copy", "cut", "green", "setbiome"));
|
||||
public final HashSet<String> regionExtend = new HashSet<>(Collections.singletonList("stack"));
|
||||
public final HashSet<String> unregioned = new HashSet<>(Arrays.asList("paste", "redo", "undo", "rotate", "flip", "generate", "schematic", "schem"));
|
||||
public final HashSet<String> unsafe1 = new HashSet<>(Arrays.asList("cs", ".s", "restore", "snapshot", "delchunks", "listchunks"));
|
||||
public final HashSet<String> restricted = new HashSet<>(Collections.singletonList("up"));
|
||||
public final HashSet<String> other = new HashSet<>(Arrays.asList("undo", "redo"));
|
||||
|
||||
public boolean checkCommand(final List<String> list, final String cmd) {
|
||||
for (final String identifier : list) {
|
||||
if (("/" + identifier).equals(cmd) || ("//" + identifier).equals(cmd) || ("/worldedit:/" + identifier).equals(cmd) || ("/worldedit:" + identifier).equals(cmd)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String reduceCmd(final String cmd, final boolean single) {
|
||||
if (cmd.startsWith("/worldedit:/")) {
|
||||
return cmd.substring(12);
|
||||
}
|
||||
if (cmd.startsWith("/worldedit:")) {
|
||||
return cmd.substring(11);
|
||||
}
|
||||
if (cmd.startsWith("//")) {
|
||||
return cmd.substring(2);
|
||||
}
|
||||
if (single && cmd.startsWith("/")) {
|
||||
return cmd.substring(1);
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
public int getInt(final String s) {
|
||||
try {
|
||||
int max = 0;
|
||||
final String[] split = s.split(",");
|
||||
for (final String rad : split) {
|
||||
final int val = Integer.parseInt(rad);
|
||||
if (val > max) {
|
||||
max = val;
|
||||
}
|
||||
}
|
||||
return max;
|
||||
} catch (final NumberFormatException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean checkVolume(final PlotPlayer player, final long volume, final long max, final Cancellable e) {
|
||||
if (volume > max) {
|
||||
MainUtil.sendMessage(player, C.WORLDEDIT_VOLUME.s().replaceAll("%current%", volume + "").replaceAll("%max%", max + ""));
|
||||
e.setCancelled(true);
|
||||
}
|
||||
if (Permissions.hasPermission(player, "plots.worldedit.bypass")) {
|
||||
MainUtil.sendMessage(player, C.WORLDEDIT_BYPASS);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean checkSelection(final Player p, final PlotPlayer pp, final int modifier, final long max, final Cancellable e) {
|
||||
final Selection selection = BukkitMain.worldEdit.getSelection(p);
|
||||
if (selection == null) {
|
||||
return true;
|
||||
}
|
||||
final BlockVector pos1 = selection.getNativeMinimumPoint().toBlockVector();
|
||||
final BlockVector pos2 = selection.getNativeMaximumPoint().toBlockVector();
|
||||
final HashSet<RegionWrapper> mask = WEManager.getMask(pp);
|
||||
final RegionWrapper region = new RegionWrapper(pos1.getBlockX(), pos2.getBlockX(), pos1.getBlockZ(), pos2.getBlockZ());
|
||||
if (Settings.REQUIRE_SELECTION) {
|
||||
String arg = null;
|
||||
if (!WEManager.regionContains(region, mask)) {
|
||||
arg = "pos1 + pos2";
|
||||
} else if (!WEManager.maskContains(mask, pos1.getBlockX(), pos1.getBlockY(), pos1.getBlockZ())) {
|
||||
arg = "pos1";
|
||||
} else if (!WEManager.maskContains(mask, pos2.getBlockX(), pos2.getBlockY(), pos2.getBlockZ())) {
|
||||
arg = "pos2";
|
||||
}
|
||||
if (arg != null) {
|
||||
e.setCancelled(true);
|
||||
MainUtil.sendMessage(pp, C.REQUIRE_SELECTION_IN_MASK, arg);
|
||||
if (Permissions.hasPermission(pp, "plots.worldedit.bypass")) {
|
||||
MainUtil.sendMessage(pp, C.WORLDEDIT_BYPASS);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!WEManager.regionContains(region, mask)) {
|
||||
MainUtil.sendMessage(pp, C.REQUIRE_SELECTION_IN_MASK, "pos1 + pos2");
|
||||
e.setCancelled(true);
|
||||
if (Permissions.hasPermission(pp, "plots.worldedit.bypass")) {
|
||||
MainUtil.sendMessage(pp, C.WORLDEDIT_BYPASS);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
final long volume = Math.abs((pos1.getBlockX() - pos2.getBlockX()) * (pos1.getBlockY() - pos2.getBlockY()) * (pos1.getBlockZ() - pos2.getBlockZ())) * modifier;
|
||||
return checkVolume(pp, volume, max, e);
|
||||
}
|
||||
|
||||
public boolean delay(final Player player, final String command, final boolean delayed) {
|
||||
if (!Settings.QUEUE_COMMANDS || !Settings.EXPERIMENTAL_FAST_ASYNC_WORLDEDIT) {
|
||||
return false;
|
||||
}
|
||||
final boolean free = SetQueue.IMP.addTask(null);
|
||||
if (free) {
|
||||
if (delayed) {
|
||||
MainUtil.sendMessage(BukkitUtil.getPlayer(player), C.WORLDEDIT_RUN, command);
|
||||
Bukkit.getServer().dispatchCommand(player, command.substring(1));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!delayed) {
|
||||
MainUtil.sendMessage(BukkitUtil.getPlayer(player), C.WORLDEDIT_DELAYED);
|
||||
}
|
||||
SetQueue.IMP.addTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
delay(player, command, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
public boolean onPlayerCommand(final PlayerCommandPreprocessEvent e) {
|
||||
final WorldEditPlugin worldedit = BukkitMain.worldEdit;
|
||||
if (worldedit == null) {
|
||||
HandlerList.unregisterAll(this);
|
||||
return true;
|
||||
}
|
||||
final Player p = e.getPlayer();
|
||||
final PlotPlayer pp = BukkitUtil.getPlayer(p);
|
||||
if (!PS.get().hasPlotArea(p.getWorld().getName())) {
|
||||
return true;
|
||||
}
|
||||
final String message = e.getMessage();
|
||||
final String cmd = message.toLowerCase();
|
||||
final boolean single = true;
|
||||
final String[] split = cmd.split(" ");
|
||||
|
||||
final long maxVolume = Settings.WE_MAX_VOLUME;
|
||||
final long maxIterations = Settings.WE_MAX_ITERATIONS;
|
||||
if (pp.getAttribute("worldedit")) {
|
||||
return true;
|
||||
}
|
||||
if (split.length >= 2) {
|
||||
final String reduced = reduceCmd(split[0], single);
|
||||
final String reduced2 = reduceCmd(split[0] + " " + split[1], single);
|
||||
if (rad1.contains(reduced)) {
|
||||
if (delay(p, message, false)) {
|
||||
e.setCancelled(true);
|
||||
return true;
|
||||
}
|
||||
final long volume = getInt(split[1]) * 256;
|
||||
return checkVolume(pp, volume, maxVolume, e);
|
||||
}
|
||||
if (rad2.contains(reduced)) {
|
||||
if (delay(p, message, false)) {
|
||||
e.setCancelled(true);
|
||||
return true;
|
||||
}
|
||||
if (split.length >= 3) {
|
||||
final long volume = getInt(split[2]) * 256;
|
||||
return checkVolume(pp, volume, maxVolume, e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (rad2_1.contains(reduced)) {
|
||||
if (delay(p, message, false)) {
|
||||
e.setCancelled(true);
|
||||
return true;
|
||||
}
|
||||
if (split.length >= 4) {
|
||||
final long volume = getInt(split[2]) * getInt(split[3]);
|
||||
return checkVolume(pp, volume, maxVolume, e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (rad2_2.contains(reduced)) {
|
||||
if (delay(p, message, false)) {
|
||||
e.setCancelled(true);
|
||||
return true;
|
||||
}
|
||||
if (split.length >= 3) {
|
||||
final long radius = getInt(split[2]);
|
||||
final long volume = radius * radius;
|
||||
return checkVolume(pp, volume, maxVolume, e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (rad2_3.contains(reduced2)) {
|
||||
if (delay(p, message, false)) {
|
||||
e.setCancelled(true);
|
||||
return true;
|
||||
}
|
||||
if (split.length >= 3) {
|
||||
if (split.length == 4) {
|
||||
final int iterations = getInt(split[3]);
|
||||
if (iterations > maxIterations) {
|
||||
MainUtil.sendMessage(pp, C.WORLDEDIT_ITERATIONS.s().replaceAll("%current%", iterations + "").replaceAll("%max%", maxIterations + ""));
|
||||
e.setCancelled(true);
|
||||
if (Permissions.hasPermission(pp, "plots.worldedit.bypass")) {
|
||||
MainUtil.sendMessage(pp, C.WORLDEDIT_BYPASS);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
final long radius = getInt(split[2]);
|
||||
final long volume = radius * radius;
|
||||
return checkVolume(pp, volume, maxVolume, e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (rad3_1.contains(reduced2)) {
|
||||
if (delay(p, message, false)) {
|
||||
e.setCancelled(true);
|
||||
return true;
|
||||
}
|
||||
if (split.length >= 3) {
|
||||
int i = 2;
|
||||
if (split[i].equalsIgnoreCase("-h")) {
|
||||
i = 3;
|
||||
}
|
||||
final long radius = getInt(split[i]);
|
||||
final long volume = radius * radius;
|
||||
return checkVolume(pp, volume, maxVolume, e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (rad3_2.contains(reduced2)) {
|
||||
if (delay(p, message, false)) {
|
||||
e.setCancelled(true);
|
||||
return true;
|
||||
}
|
||||
if (split.length >= 4) {
|
||||
int i = 3;
|
||||
if (split[i].equalsIgnoreCase("-h")) {
|
||||
i = 4;
|
||||
}
|
||||
final long radius = getInt(split[i]);
|
||||
final long volume = radius * radius;
|
||||
return checkVolume(pp, volume, maxVolume, e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (regionExtend.contains(reduced)) {
|
||||
if (delay(p, message, false)) {
|
||||
e.setCancelled(true);
|
||||
return true;
|
||||
}
|
||||
return checkSelection(p, pp, getInt(split[1]), maxVolume, e);
|
||||
}
|
||||
}
|
||||
final String reduced = reduceCmd(split[0], single);
|
||||
if (Settings.WE_BLACKLIST.contains(reduced)) {
|
||||
MainUtil.sendMessage(pp, C.WORLDEDIT_UNSAFE);
|
||||
e.setCancelled(true);
|
||||
if (Permissions.hasPermission(pp, "plots.worldedit.bypass")) {
|
||||
MainUtil.sendMessage(pp, C.WORLDEDIT_BYPASS);
|
||||
}
|
||||
}
|
||||
if (restricted.contains(reduced)) {
|
||||
final Plot plot = pp.getCurrentPlot();
|
||||
if ((plot != null) && plot.isAdded(pp.getUUID())) {
|
||||
if (delay(p, message, false)) {
|
||||
e.setCancelled(true);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
e.setCancelled(true);
|
||||
MainUtil.sendMessage(pp, C.NO_PLOT_PERMS);
|
||||
if (Permissions.hasPermission(pp, "plots.worldedit.bypass")) {
|
||||
MainUtil.sendMessage(pp, C.WORLDEDIT_BYPASS);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (region.contains(reduced)) {
|
||||
if (delay(p, message, false)) {
|
||||
e.setCancelled(true);
|
||||
return true;
|
||||
}
|
||||
return checkSelection(p, pp, 1, maxVolume, e);
|
||||
}
|
||||
if (other.contains(reduced)) {
|
||||
if (delay(p, message, false)) {
|
||||
e.setCancelled(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
package com.plotsquared.bukkit.object;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import com.intellectualcrafters.plot.object.LazyBlock;
|
||||
import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
|
||||
public class BukkitLazyBlock extends LazyBlock {
|
||||
|
||||
private int id;
|
||||
private Block block;
|
||||
private PlotBlock pb;
|
||||
|
||||
public BukkitLazyBlock(final int id, final Block block) {
|
||||
this.id = id;
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
public BukkitLazyBlock(final PlotBlock pb) {
|
||||
id = pb.id;
|
||||
this.pb = pb;
|
||||
}
|
||||
|
||||
public BukkitLazyBlock(final Block block) {
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotBlock getPlotBlock() {
|
||||
if (pb != null) {
|
||||
return pb;
|
||||
}
|
||||
if (id == 0) {
|
||||
id = block.getTypeId();
|
||||
}
|
||||
byte data;
|
||||
switch (id) {
|
||||
case 0:
|
||||
case 2:
|
||||
case 4:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 24:
|
||||
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:
|
||||
data = 0;
|
||||
break;
|
||||
default:
|
||||
data = block.getData();
|
||||
break;
|
||||
}
|
||||
pb = new PlotBlock((short) id, data);
|
||||
return pb;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
if (id == 0) {
|
||||
id = block.getTypeId();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.plotsquared.bukkit.object;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
import com.intellectualcrafters.plot.object.OfflinePlotPlayer;
|
||||
|
||||
public class BukkitOfflinePlayer implements OfflinePlotPlayer {
|
||||
|
||||
public final OfflinePlayer player;
|
||||
|
||||
/**
|
||||
* Please do not use this method. Instead use BukkitUtil.getPlayer(Player), as it caches player objects.
|
||||
* @param player
|
||||
*/
|
||||
public BukkitOfflinePlayer(final OfflinePlayer player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return player.getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastPlayed() {
|
||||
return player.getLastPlayed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return player.isOnline();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return player.getName();
|
||||
}
|
||||
}
|
@ -0,0 +1,242 @@
|
||||
package com.plotsquared.bukkit.object;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Effect;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.WeatherType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
import org.bukkit.permissions.Permission;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
import com.intellectualcrafters.plot.config.C;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.util.EconHandler;
|
||||
import com.intellectualcrafters.plot.util.PlotGamemode;
|
||||
import com.intellectualcrafters.plot.util.PlotWeather;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandler;
|
||||
import com.plotsquared.bukkit.util.BukkitUtil;
|
||||
|
||||
public class BukkitPlayer extends PlotPlayer {
|
||||
|
||||
public final Player player;
|
||||
public boolean offline;
|
||||
private UUID uuid;
|
||||
private String name;
|
||||
private long last = 0;
|
||||
|
||||
/**
|
||||
* Please do not use this method. Instead use BukkitUtil.getPlayer(Player), as it caches player objects.
|
||||
* @param player
|
||||
*/
|
||||
public BukkitPlayer(final Player player) {
|
||||
this.player = player;
|
||||
super.populatePersistentMetaMap();
|
||||
}
|
||||
|
||||
public BukkitPlayer(final Player player, final boolean offline) {
|
||||
this.player = player;
|
||||
this.offline = offline;
|
||||
super.populatePersistentMetaMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getPreviousLogin() {
|
||||
if (last == 0) {
|
||||
last = player.getLastPlayed();
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
final Location loc = super.getLocation();
|
||||
return loc == null ? BukkitUtil.getLocation(player) : loc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
if (uuid == null) {
|
||||
uuid = UUIDHandler.getUUID(this);
|
||||
}
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(final String node) {
|
||||
if (offline && EconHandler.manager != null) {
|
||||
return EconHandler.manager.hasPermission(getName(), node);
|
||||
}
|
||||
return player.hasPermission(node);
|
||||
}
|
||||
|
||||
public Permission getPermission(final String node) {
|
||||
final PluginManager manager = Bukkit.getPluginManager();
|
||||
Permission perm = manager.getPermission(node);
|
||||
if (perm == null) {
|
||||
final String[] nodes = node.split("\\.");
|
||||
perm = new Permission(node);
|
||||
final StringBuilder n = new StringBuilder();
|
||||
for (int i = 0; i < nodes.length - 1; i++) {
|
||||
n.append(nodes[i]).append(".");
|
||||
if (!node.equals(n + C.PERMISSION_STAR.s())) {
|
||||
final Permission parent = getPermission(n + C.PERMISSION_STAR.s());
|
||||
if (parent != null) {
|
||||
perm.addParent(parent, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
manager.addPermission(perm);
|
||||
}
|
||||
manager.recalculatePermissionDefaults(perm);
|
||||
perm.recalculatePermissibles();
|
||||
return perm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(final String message) {
|
||||
player.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teleport(final Location loc) {
|
||||
if (Math.abs(loc.getX()) >= 30000000 || Math.abs(loc.getZ()) >= 30000000) {
|
||||
return;
|
||||
}
|
||||
player.teleport(new org.bukkit.Location(BukkitUtil.getWorld(loc.getWorld()), loc.getX() + 0.5, loc.getY(), loc.getZ() + 0.5, loc.getYaw(), loc.getPitch()), TeleportCause.COMMAND);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
if (name == null) {
|
||||
name = player.getName();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return !offline && player.isOnline();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompassTarget(final Location loc) {
|
||||
player.setCompassTarget(new org.bukkit.Location(BukkitUtil.getWorld(loc.getWorld()), loc.getX(), loc.getY(), loc.getZ()));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocationFull() {
|
||||
return BukkitUtil.getLocationFull(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String key) {
|
||||
setPersistentMeta("attrib_" + key, new byte[]{(byte) 1});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAttribute(String key) {
|
||||
if (!hasPersistentMeta(key)) {
|
||||
return false;
|
||||
}
|
||||
return getPersistentMeta("attrib_" + key)[0] == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String key) {
|
||||
removePersistentMeta("attrib_" + key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadData() {
|
||||
if (!player.isOnline()) {
|
||||
player.loadData();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
player.saveData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWeather(final PlotWeather weather) {
|
||||
switch (weather) {
|
||||
case CLEAR:
|
||||
player.setPlayerWeather(WeatherType.CLEAR);
|
||||
return;
|
||||
case RAIN:
|
||||
player.setPlayerWeather(WeatherType.DOWNFALL);
|
||||
return;
|
||||
case RESET:
|
||||
player.resetPlayerWeather();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotGamemode getGamemode() {
|
||||
switch (player.getGameMode()) {
|
||||
case ADVENTURE:
|
||||
return PlotGamemode.ADVENTURE;
|
||||
case CREATIVE:
|
||||
return PlotGamemode.CREATIVE;
|
||||
case SPECTATOR:
|
||||
return PlotGamemode.SPECTATOR;
|
||||
case SURVIVAL:
|
||||
return PlotGamemode.SURVIVAL;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGamemode(final PlotGamemode gamemode) {
|
||||
switch (gamemode) {
|
||||
case ADVENTURE:
|
||||
player.setGameMode(GameMode.ADVENTURE);
|
||||
return;
|
||||
case CREATIVE:
|
||||
player.setGameMode(GameMode.CREATIVE);
|
||||
return;
|
||||
case SPECTATOR:
|
||||
player.setGameMode(GameMode.SPECTATOR);
|
||||
return;
|
||||
case SURVIVAL:
|
||||
player.setGameMode(GameMode.SURVIVAL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTime(final long time) {
|
||||
if (time != Long.MAX_VALUE) {
|
||||
player.setPlayerTime(time, false);
|
||||
} else {
|
||||
player.resetPlayerTime();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFlight(final boolean fly) {
|
||||
player.setAllowFlight(fly);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playMusic(final Location loc, final int id) {
|
||||
player.playEffect(BukkitUtil.getLocation(loc), Effect.RECORD_PLAY, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void kick(final String message) {
|
||||
player.kickPlayer(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBanned() {
|
||||
return player.isBanned();
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.plotsquared.bukkit.object.entity;
|
||||
|
||||
public class AgeableStats {
|
||||
public int age;
|
||||
public boolean locked;
|
||||
public boolean adult;
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.plotsquared.bukkit.object.entity;
|
||||
|
||||
public class ArmorStandStats {
|
||||
public float[] head = new float[3];
|
||||
public float[] body = new float[3];
|
||||
public float[] leftLeg = new float[3];
|
||||
public float[] rightLeg = new float[3];
|
||||
public float[] leftArm = new float[3];
|
||||
public float[] rightArm = new float[3];
|
||||
public boolean arms;
|
||||
public boolean noplate;
|
||||
public boolean nogravity;
|
||||
public boolean invisible;
|
||||
public boolean small;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.plotsquared.bukkit.object.entity;
|
||||
|
||||
|
||||
public class EntityBaseStats {
|
||||
public EntityWrapper passenger;
|
||||
public float fall;
|
||||
public short fire;
|
||||
public int age;
|
||||
public double v_z;
|
||||
public double v_y;
|
||||
public double v_x;
|
||||
}
|
@ -0,0 +1,682 @@
|
||||
package com.plotsquared.bukkit.object.entity;
|
||||
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import org.bukkit.Art;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Rotation;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Ageable;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Guardian;
|
||||
import org.bukkit.entity.Horse;
|
||||
import org.bukkit.entity.Horse.Color;
|
||||
import org.bukkit.entity.Horse.Style;
|
||||
import org.bukkit.entity.Horse.Variant;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Painting;
|
||||
import org.bukkit.entity.Rabbit;
|
||||
import org.bukkit.entity.Rabbit.Type;
|
||||
import org.bukkit.entity.Sheep;
|
||||
import org.bukkit.entity.Skeleton;
|
||||
import org.bukkit.entity.Skeleton.SkeletonType;
|
||||
import org.bukkit.entity.Tameable;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.EulerAngle;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public class EntityWrapper {
|
||||
|
||||
public EntityType type;
|
||||
public float yaw;
|
||||
public float pitch;
|
||||
public double x;
|
||||
public double y;
|
||||
public double z;
|
||||
public short depth;
|
||||
public EntityBaseStats base = null;
|
||||
// Extended
|
||||
public ItemStack stack;
|
||||
public ItemStack[] inventory;
|
||||
public byte dataByte;
|
||||
public byte dataByte2;
|
||||
public String dataString;
|
||||
public LivingEntityStats lived;
|
||||
public AgeableStats aged;
|
||||
public TameableStats tamed;
|
||||
private HorseStats horse;
|
||||
private ArmorStandStats stand;
|
||||
|
||||
private int hash;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public EntityWrapper(final org.bukkit.entity.Entity entity, final short depth) {
|
||||
hash = entity.getEntityId();
|
||||
this.depth = depth;
|
||||
final Location loc = entity.getLocation();
|
||||
yaw = loc.getYaw();
|
||||
pitch = loc.getPitch();
|
||||
x = loc.getX();
|
||||
y = loc.getY();
|
||||
z = loc.getZ();
|
||||
type = entity.getType();
|
||||
if (depth == 0) {
|
||||
return;
|
||||
}
|
||||
base = new EntityBaseStats();
|
||||
final Entity p = entity.getPassenger();
|
||||
if (p != null) {
|
||||
base.passenger = new EntityWrapper(p, depth);
|
||||
}
|
||||
base.fall = entity.getFallDistance();
|
||||
base.fire = (short) entity.getFireTicks();
|
||||
base.age = entity.getTicksLived();
|
||||
final Vector velocity = entity.getVelocity();
|
||||
base.v_x = velocity.getX();
|
||||
base.v_y = velocity.getY();
|
||||
base.v_z = velocity.getZ();
|
||||
if (depth == 1) {
|
||||
return;
|
||||
}
|
||||
switch (entity.getType()) {
|
||||
case ARROW:
|
||||
case BOAT:
|
||||
case COMPLEX_PART:
|
||||
case EGG:
|
||||
case ENDER_CRYSTAL:
|
||||
case ENDER_PEARL:
|
||||
case ENDER_SIGNAL:
|
||||
case EXPERIENCE_ORB:
|
||||
case FALLING_BLOCK:
|
||||
case FIREBALL:
|
||||
case FIREWORK:
|
||||
case FISHING_HOOK:
|
||||
case LEASH_HITCH:
|
||||
case LIGHTNING:
|
||||
case MINECART:
|
||||
case MINECART_COMMAND:
|
||||
case MINECART_MOB_SPAWNER:
|
||||
case MINECART_TNT:
|
||||
case PLAYER:
|
||||
case PRIMED_TNT:
|
||||
case SLIME:
|
||||
case SMALL_FIREBALL:
|
||||
case SNOWBALL:
|
||||
case MINECART_FURNACE:
|
||||
case SPLASH_POTION:
|
||||
case THROWN_EXP_BOTTLE:
|
||||
case WEATHER:
|
||||
case WITHER_SKULL:
|
||||
case UNKNOWN: {
|
||||
// Do this stuff later
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
PS.debug("&cCOULD NOT IDENTIFY ENTITY: " + entity.getType());
|
||||
return;
|
||||
}
|
||||
// MISC //
|
||||
case DROPPED_ITEM: {
|
||||
final Item item = (Item) entity;
|
||||
stack = item.getItemStack();
|
||||
return;
|
||||
}
|
||||
case ITEM_FRAME: {
|
||||
final ItemFrame itemframe = (ItemFrame) entity;
|
||||
x = Math.floor(x);
|
||||
y = Math.floor(y);
|
||||
z = Math.floor(z);
|
||||
dataByte = getOrdinal(Rotation.values(), itemframe.getRotation());
|
||||
stack = itemframe.getItem().clone();
|
||||
return;
|
||||
}
|
||||
case PAINTING: {
|
||||
final Painting painting = (Painting) entity;
|
||||
x = Math.floor(x);
|
||||
y = Math.floor(y);
|
||||
z = Math.floor(z);
|
||||
final Art a = painting.getArt();
|
||||
dataByte = getOrdinal(BlockFace.values(), painting.getFacing());
|
||||
final int h = a.getBlockHeight();
|
||||
if ((h % 2) == 0) {
|
||||
y -= 1;
|
||||
}
|
||||
dataString = a.name();
|
||||
return;
|
||||
}
|
||||
// END MISC //
|
||||
// INVENTORY HOLDER //
|
||||
case MINECART_CHEST: {
|
||||
storeInventory((InventoryHolder) entity);
|
||||
return;
|
||||
}
|
||||
case MINECART_HOPPER: {
|
||||
storeInventory((InventoryHolder) entity);
|
||||
return;
|
||||
}
|
||||
// START LIVING ENTITY //
|
||||
// START AGEABLE //
|
||||
// START TAMEABLE //
|
||||
case HORSE: {
|
||||
final Horse horse = (Horse) entity;
|
||||
this.horse = new HorseStats();
|
||||
this.horse.jump = horse.getJumpStrength();
|
||||
this.horse.chest = horse.isCarryingChest();
|
||||
this.horse.variant = getOrdinal(Variant.values(), horse.getVariant());
|
||||
this.horse.style = getOrdinal(Style.values(), horse.getStyle());
|
||||
this.horse.color = getOrdinal(Color.values(), horse.getColor());
|
||||
storeTameable((Tameable) entity);
|
||||
storeAgeable((Ageable) entity);
|
||||
storeLiving((LivingEntity) entity);
|
||||
storeInventory((InventoryHolder) entity);
|
||||
return;
|
||||
}
|
||||
// END INVENTORY HOLDER //
|
||||
case WOLF:
|
||||
case OCELOT: {
|
||||
storeTameable((Tameable) entity);
|
||||
storeAgeable((Ageable) entity);
|
||||
storeLiving((LivingEntity) entity);
|
||||
return;
|
||||
}
|
||||
// END AMEABLE //
|
||||
case SHEEP: {
|
||||
final Sheep sheep = (Sheep) entity;
|
||||
dataByte = (byte) ((sheep).isSheared() ? 1 : 0);
|
||||
dataByte2 = sheep.getColor().getDyeData();
|
||||
storeAgeable((Ageable) entity);
|
||||
storeLiving((LivingEntity) entity);
|
||||
return;
|
||||
}
|
||||
case VILLAGER:
|
||||
case CHICKEN:
|
||||
case COW:
|
||||
case MUSHROOM_COW:
|
||||
case PIG: {
|
||||
storeAgeable((Ageable) entity);
|
||||
storeLiving((LivingEntity) entity);
|
||||
return;
|
||||
}
|
||||
// END AGEABLE //
|
||||
case RABBIT: { // NEW
|
||||
dataByte = getOrdinal(Type.values(), ((Rabbit) entity).getRabbitType());
|
||||
storeAgeable((Ageable) entity);
|
||||
storeLiving((LivingEntity) entity);
|
||||
return;
|
||||
}
|
||||
case GUARDIAN: { // NEW
|
||||
dataByte = (byte) (((Guardian) entity).isElder() ? 1 : 0);
|
||||
storeLiving((LivingEntity) entity);
|
||||
return;
|
||||
}
|
||||
case SKELETON: { // NEW
|
||||
dataByte = (byte) ((Skeleton) entity).getSkeletonType().getId();
|
||||
storeLiving((LivingEntity) entity);
|
||||
return;
|
||||
}
|
||||
case ARMOR_STAND: { // NEW
|
||||
// CHECK positions
|
||||
final ArmorStand stand = (ArmorStand) entity;
|
||||
inventory = new ItemStack[] { stand.getItemInHand().clone(), stand.getHelmet().clone(), stand.getChestplate().clone(), stand.getLeggings().clone(), stand.getBoots().clone() };
|
||||
storeLiving((LivingEntity) entity);
|
||||
this.stand = new ArmorStandStats();
|
||||
|
||||
final EulerAngle head = stand.getHeadPose();
|
||||
this.stand.head[0] = (float) head.getX();
|
||||
this.stand.head[1] = (float) head.getY();
|
||||
this.stand.head[2] = (float) head.getZ();
|
||||
|
||||
final EulerAngle body = stand.getBodyPose();
|
||||
this.stand.body[0] = (float) body.getX();
|
||||
this.stand.body[1] = (float) body.getY();
|
||||
this.stand.body[2] = (float) body.getZ();
|
||||
|
||||
final EulerAngle leftLeg = stand.getLeftLegPose();
|
||||
this.stand.leftLeg[0] = (float) leftLeg.getX();
|
||||
this.stand.leftLeg[1] = (float) leftLeg.getY();
|
||||
this.stand.leftLeg[2] = (float) leftLeg.getZ();
|
||||
|
||||
final EulerAngle rightLeg = stand.getRightLegPose();
|
||||
this.stand.rightLeg[0] = (float) rightLeg.getX();
|
||||
this.stand.rightLeg[1] = (float) rightLeg.getY();
|
||||
this.stand.rightLeg[2] = (float) rightLeg.getZ();
|
||||
|
||||
final EulerAngle leftArm = stand.getLeftArmPose();
|
||||
this.stand.leftArm[0] = (float) leftArm.getX();
|
||||
this.stand.leftArm[1] = (float) leftArm.getY();
|
||||
this.stand.leftArm[2] = (float) leftArm.getZ();
|
||||
|
||||
final EulerAngle rightArm = stand.getRightArmPose();
|
||||
this.stand.rightArm[0] = (float) rightArm.getX();
|
||||
this.stand.rightArm[1] = (float) rightArm.getY();
|
||||
this.stand.rightArm[2] = (float) rightArm.getZ();
|
||||
|
||||
if (stand.hasArms()) {
|
||||
this.stand.arms = true;
|
||||
}
|
||||
if (!stand.hasBasePlate()) {
|
||||
this.stand.noplate = true;
|
||||
}
|
||||
if (!stand.hasGravity()) {
|
||||
this.stand.nogravity = true;
|
||||
}
|
||||
if (!stand.isVisible()) {
|
||||
this.stand.invisible = true;
|
||||
}
|
||||
if (stand.isSmall()) {
|
||||
this.stand.small = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
case ENDERMITE: // NEW
|
||||
case BAT:
|
||||
case ENDER_DRAGON:
|
||||
case GHAST:
|
||||
case MAGMA_CUBE:
|
||||
case SQUID:
|
||||
case PIG_ZOMBIE:
|
||||
case ZOMBIE:
|
||||
case WITHER:
|
||||
case WITCH:
|
||||
case SPIDER:
|
||||
case CAVE_SPIDER:
|
||||
case SILVERFISH:
|
||||
case GIANT:
|
||||
case ENDERMAN:
|
||||
case CREEPER:
|
||||
case BLAZE:
|
||||
case SNOWMAN:
|
||||
case IRON_GOLEM: {
|
||||
storeLiving((LivingEntity) entity);
|
||||
return;
|
||||
}
|
||||
// END LIVING //
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return hash == obj.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public void storeInventory(final InventoryHolder held) {
|
||||
inventory = held.getInventory().getContents().clone();
|
||||
}
|
||||
|
||||
private void restoreLiving(final LivingEntity entity) {
|
||||
entity.setCanPickupItems(lived.loot);
|
||||
if (lived.name != null) {
|
||||
entity.setCustomName(lived.name);
|
||||
entity.setCustomNameVisible(lived.visible);
|
||||
}
|
||||
if ((lived.potions != null) && (!lived.potions.isEmpty())) {
|
||||
entity.addPotionEffects(lived.potions);
|
||||
}
|
||||
entity.setRemainingAir(lived.air);
|
||||
entity.setRemoveWhenFarAway(lived.persistent);
|
||||
if (lived.equipped) {
|
||||
final EntityEquipment equipment = entity.getEquipment();
|
||||
equipment.setItemInHand(lived.hands);
|
||||
equipment.setHelmet(lived.helmet);
|
||||
equipment.setChestplate(lived.chestplate);
|
||||
equipment.setLeggings(lived.leggings);
|
||||
equipment.setBoots(lived.boots);
|
||||
}
|
||||
if (lived.leashed) {
|
||||
// TODO leashes
|
||||
// World world = entity.getWorld();
|
||||
// Entity leash = world.spawnEntity(new Location(world, Math.floor(x) + lived.leash_x, Math.floor(y) + lived.leash_y, Math
|
||||
// .floor(z) + lived.leash_z), EntityType.LEASH_HITCH);
|
||||
// entity.setLeashHolder(leash);
|
||||
}
|
||||
}
|
||||
|
||||
private void restoreInventory(final InventoryHolder entity) {
|
||||
entity.getInventory().setContents(inventory);
|
||||
}
|
||||
|
||||
public void storeLiving(final LivingEntity lived) {
|
||||
this.lived = new LivingEntityStats();
|
||||
this.lived.potions = lived.getActivePotionEffects();
|
||||
this.lived.loot = lived.getCanPickupItems();
|
||||
this.lived.name = lived.getCustomName();
|
||||
this.lived.visible = lived.isCustomNameVisible();
|
||||
this.lived.health = (float) lived.getHealth();
|
||||
this.lived.air = (short) lived.getRemainingAir();
|
||||
this.lived.persistent = lived.getRemoveWhenFarAway();
|
||||
this.lived.leashed = lived.isLeashed();
|
||||
if (this.lived.leashed) {
|
||||
final Location loc = lived.getLeashHolder().getLocation();
|
||||
this.lived.leash_x = (short) (x - loc.getBlockX());
|
||||
this.lived.leash_y = (short) (y - loc.getBlockY());
|
||||
this.lived.leash_z = (short) (z - loc.getBlockZ());
|
||||
}
|
||||
final EntityEquipment equipment = lived.getEquipment();
|
||||
this.lived.equipped = equipment != null;
|
||||
if (this.lived.equipped) {
|
||||
this.lived.hands = equipment.getItemInHand().clone();
|
||||
this.lived.boots = equipment.getBoots().clone();
|
||||
this.lived.leggings = equipment.getLeggings().clone();
|
||||
this.lived.chestplate = equipment.getChestplate().clone();
|
||||
this.lived.helmet = equipment.getHelmet().clone();
|
||||
}
|
||||
}
|
||||
|
||||
private void restoreTameable(final Tameable entity) {
|
||||
if (tamed.tamed) {
|
||||
if (tamed.owner != null) {
|
||||
entity.setTamed(true);
|
||||
entity.setOwner(tamed.owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void restoreAgeable(final Ageable entity) {
|
||||
if (!aged.adult) {
|
||||
entity.setBaby();
|
||||
}
|
||||
entity.setAgeLock(aged.locked);
|
||||
if (aged.age > 0) {
|
||||
entity.setAge(aged.age);
|
||||
}
|
||||
}
|
||||
|
||||
public void storeAgeable(final Ageable aged) {
|
||||
this.aged = new AgeableStats();
|
||||
this.aged.age = aged.getAge();
|
||||
this.aged.locked = aged.getAgeLock();
|
||||
this.aged.adult = aged.isAdult();
|
||||
}
|
||||
|
||||
public void storeTameable(final Tameable tamed) {
|
||||
this.tamed = new TameableStats();
|
||||
this.tamed.owner = tamed.getOwner();
|
||||
this.tamed.tamed = tamed.isTamed();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public Entity spawn(final World world, final int x_offset, final int z_offset) {
|
||||
final Location loc = new Location(world, x + x_offset, y, z + z_offset);
|
||||
loc.setYaw(yaw);
|
||||
loc.setPitch(pitch);
|
||||
if (type.isSpawnable()) {
|
||||
return null;
|
||||
}
|
||||
Entity entity;
|
||||
switch (type) {
|
||||
case DROPPED_ITEM: {
|
||||
return world.dropItem(loc, stack);
|
||||
}
|
||||
case PLAYER:
|
||||
case LEASH_HITCH: {
|
||||
return null;
|
||||
}
|
||||
case ITEM_FRAME: {
|
||||
entity = world.spawn(loc, ItemFrame.class);
|
||||
break;
|
||||
}
|
||||
case PAINTING: {
|
||||
entity = world.spawn(loc, Painting.class);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
entity = world.spawnEntity(loc, type);
|
||||
break;
|
||||
}
|
||||
if (depth == 0) {
|
||||
return entity;
|
||||
}
|
||||
if (base.passenger != null) {
|
||||
try {
|
||||
entity.setPassenger(base.passenger.spawn(world, x_offset, z_offset));
|
||||
} catch (final Exception e) {}
|
||||
}
|
||||
if (base.fall != 0) {
|
||||
entity.setFallDistance(base.fall);
|
||||
}
|
||||
if (base.fire != 0) {
|
||||
entity.setFireTicks(base.fire);
|
||||
}
|
||||
if (base.age != 0) {
|
||||
entity.setTicksLived(base.age);
|
||||
}
|
||||
entity.setVelocity(new Vector(base.v_x, base.v_y, base.v_z));
|
||||
if (depth == 1) {
|
||||
return entity;
|
||||
}
|
||||
switch (entity.getType()) {
|
||||
case ARROW:
|
||||
case BOAT:
|
||||
case COMPLEX_PART:
|
||||
case EGG:
|
||||
case ENDER_CRYSTAL:
|
||||
case ENDER_PEARL:
|
||||
case ENDER_SIGNAL:
|
||||
case EXPERIENCE_ORB:
|
||||
case FALLING_BLOCK:
|
||||
case FIREBALL:
|
||||
case FIREWORK:
|
||||
case FISHING_HOOK:
|
||||
case LEASH_HITCH:
|
||||
case LIGHTNING:
|
||||
case MINECART:
|
||||
case MINECART_COMMAND:
|
||||
case MINECART_MOB_SPAWNER:
|
||||
case MINECART_TNT:
|
||||
case PLAYER:
|
||||
case PRIMED_TNT:
|
||||
case SLIME:
|
||||
case SMALL_FIREBALL:
|
||||
case SNOWBALL:
|
||||
case SPLASH_POTION:
|
||||
case THROWN_EXP_BOTTLE:
|
||||
case WEATHER:
|
||||
case WITHER_SKULL:
|
||||
case MINECART_FURNACE:
|
||||
case UNKNOWN: {
|
||||
// Do this stuff later
|
||||
return entity;
|
||||
}
|
||||
default: {
|
||||
PS.debug("&cCOULD NOT IDENTIFY ENTITY: " + entity.getType());
|
||||
return entity;
|
||||
}
|
||||
// MISC //
|
||||
case ITEM_FRAME: {
|
||||
final ItemFrame itemframe = (ItemFrame) entity;
|
||||
itemframe.setRotation(Rotation.values()[dataByte]);
|
||||
itemframe.setItem(stack);
|
||||
return entity;
|
||||
}
|
||||
case PAINTING: {
|
||||
final Painting painting = (Painting) entity;
|
||||
painting.setFacingDirection(BlockFace.values()[dataByte], true);
|
||||
painting.setArt(Art.getByName(dataString), true);
|
||||
return entity;
|
||||
}
|
||||
// END MISC //
|
||||
// INVENTORY HOLDER //
|
||||
case MINECART_CHEST: {
|
||||
restoreInventory((InventoryHolder) entity);
|
||||
return entity;
|
||||
}
|
||||
case MINECART_HOPPER: {
|
||||
restoreInventory((InventoryHolder) entity);
|
||||
return entity;
|
||||
}
|
||||
// START LIVING ENTITY //
|
||||
// START AGEABLE //
|
||||
// START TAMEABLE //
|
||||
case HORSE: {
|
||||
final Horse horse = (Horse) entity;
|
||||
horse.setJumpStrength(this.horse.jump);
|
||||
horse.setCarryingChest(this.horse.chest);
|
||||
horse.setVariant(Variant.values()[this.horse.variant]);
|
||||
horse.setStyle(Style.values()[this.horse.style]);
|
||||
horse.setColor(Color.values()[this.horse.color]);
|
||||
restoreTameable((Tameable) entity);
|
||||
restoreAgeable((Ageable) entity);
|
||||
restoreLiving((LivingEntity) entity);
|
||||
restoreInventory((InventoryHolder) entity);
|
||||
return entity;
|
||||
}
|
||||
// END INVENTORY HOLDER //
|
||||
case WOLF:
|
||||
case OCELOT: {
|
||||
restoreTameable((Tameable) entity);
|
||||
restoreAgeable((Ageable) entity);
|
||||
restoreLiving((LivingEntity) entity);
|
||||
return entity;
|
||||
}
|
||||
// END AGEABLE //
|
||||
case SHEEP: {
|
||||
final Sheep sheep = (Sheep) entity;
|
||||
if (dataByte == 1) {
|
||||
sheep.setSheared(true);
|
||||
}
|
||||
if (dataByte2 != 0) {
|
||||
sheep.setColor(DyeColor.getByDyeData(dataByte2));
|
||||
}
|
||||
restoreAgeable((Ageable) entity);
|
||||
restoreLiving((LivingEntity) entity);
|
||||
return entity;
|
||||
}
|
||||
case VILLAGER:
|
||||
case CHICKEN:
|
||||
case COW:
|
||||
case MUSHROOM_COW:
|
||||
case PIG: {
|
||||
restoreAgeable((Ageable) entity);
|
||||
restoreLiving((LivingEntity) entity);
|
||||
return entity;
|
||||
}
|
||||
// END AGEABLE //
|
||||
case RABBIT: { // NEW
|
||||
if (dataByte != 0) {
|
||||
((Rabbit) entity).setRabbitType(Type.values()[dataByte]);
|
||||
}
|
||||
restoreAgeable((Ageable) entity);
|
||||
restoreLiving((LivingEntity) entity);
|
||||
return entity;
|
||||
}
|
||||
case GUARDIAN: { // NEW
|
||||
if (dataByte != 0) {
|
||||
((Guardian) entity).setElder(true);
|
||||
}
|
||||
restoreLiving((LivingEntity) entity);
|
||||
return entity;
|
||||
}
|
||||
case SKELETON: { // NEW
|
||||
if (dataByte != 0) {
|
||||
((Skeleton) entity).setSkeletonType(SkeletonType.values()[dataByte]);
|
||||
}
|
||||
storeLiving((LivingEntity) entity);
|
||||
return entity;
|
||||
}
|
||||
case ARMOR_STAND: { // NEW
|
||||
// CHECK positions
|
||||
final ArmorStand stand = (ArmorStand) entity;
|
||||
if (inventory[0] != null) {
|
||||
stand.setItemInHand(inventory[0]);
|
||||
}
|
||||
if (inventory[1] != null) {
|
||||
stand.setHelmet(inventory[1]);
|
||||
}
|
||||
if (inventory[2] != null) {
|
||||
stand.setChestplate(inventory[2]);
|
||||
}
|
||||
if (inventory[3] != null) {
|
||||
stand.setLeggings(inventory[3]);
|
||||
}
|
||||
if (inventory[4] != null) {
|
||||
stand.setBoots(inventory[4]);
|
||||
}
|
||||
if ((this.stand.head[0] != 0) || (this.stand.head[1] != 0) || (this.stand.head[2] != 0)) {
|
||||
final EulerAngle pose = new EulerAngle(this.stand.head[0], this.stand.head[1], this.stand.head[2]);
|
||||
stand.setHeadPose(pose);
|
||||
}
|
||||
if ((this.stand.body[0] != 0) || (this.stand.body[1] != 0) || (this.stand.body[2] != 0)) {
|
||||
final EulerAngle pose = new EulerAngle(this.stand.body[0], this.stand.body[1], this.stand.body[2]);
|
||||
stand.setBodyPose(pose);
|
||||
}
|
||||
if ((this.stand.leftLeg[0] != 0) || (this.stand.leftLeg[1] != 0) || (this.stand.leftLeg[2] != 0)) {
|
||||
final EulerAngle pose = new EulerAngle(this.stand.leftLeg[0], this.stand.leftLeg[1], this.stand.leftLeg[2]);
|
||||
stand.setLeftLegPose(pose);
|
||||
}
|
||||
if ((this.stand.rightLeg[0] != 0) || (this.stand.rightLeg[1] != 0) || (this.stand.rightLeg[2] != 0)) {
|
||||
final EulerAngle pose = new EulerAngle(this.stand.rightLeg[0], this.stand.rightLeg[1], this.stand.rightLeg[2]);
|
||||
stand.setRightLegPose(pose);
|
||||
}
|
||||
if ((this.stand.leftArm[0] != 0) || (this.stand.leftArm[1] != 0) || (this.stand.leftArm[2] != 0)) {
|
||||
final EulerAngle pose = new EulerAngle(this.stand.leftArm[0], this.stand.leftArm[1], this.stand.leftArm[2]);
|
||||
stand.setLeftArmPose(pose);
|
||||
}
|
||||
if ((this.stand.rightArm[0] != 0) || (this.stand.rightArm[1] != 0) || (this.stand.rightArm[2] != 0)) {
|
||||
final EulerAngle pose = new EulerAngle(this.stand.rightArm[0], this.stand.rightArm[1], this.stand.rightArm[2]);
|
||||
stand.setRightArmPose(pose);
|
||||
}
|
||||
if (this.stand.invisible) {
|
||||
stand.setVisible(false);
|
||||
}
|
||||
if (this.stand.arms) {
|
||||
stand.setArms(true);
|
||||
}
|
||||
if (this.stand.nogravity) {
|
||||
stand.setGravity(false);
|
||||
}
|
||||
if (this.stand.noplate) {
|
||||
stand.setBasePlate(false);
|
||||
}
|
||||
if (this.stand.small) {
|
||||
stand.setSmall(true);
|
||||
}
|
||||
restoreLiving((LivingEntity) entity);
|
||||
return entity;
|
||||
}
|
||||
case ENDERMITE: // NEW
|
||||
case BAT:
|
||||
case ENDER_DRAGON:
|
||||
case GHAST:
|
||||
case MAGMA_CUBE:
|
||||
case SQUID:
|
||||
case PIG_ZOMBIE:
|
||||
case ZOMBIE:
|
||||
case WITHER:
|
||||
case WITCH:
|
||||
case SPIDER:
|
||||
case CAVE_SPIDER:
|
||||
case SILVERFISH:
|
||||
case GIANT:
|
||||
case ENDERMAN:
|
||||
case CREEPER:
|
||||
case BLAZE:
|
||||
case SNOWMAN:
|
||||
case IRON_GOLEM: {
|
||||
restoreLiving((LivingEntity) entity);
|
||||
return entity;
|
||||
}
|
||||
// END LIVING //
|
||||
}
|
||||
}
|
||||
|
||||
private byte getOrdinal(final Object[] list, final Object value) {
|
||||
for (byte i = 0; i < list.length; i++) {
|
||||
if (list[i].equals(value)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.plotsquared.bukkit.object.entity;
|
||||
|
||||
public class HorseStats {
|
||||
public double jump;
|
||||
public boolean chest;
|
||||
public int variant;
|
||||
public int color;
|
||||
public int style;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.plotsquared.bukkit.object.entity;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
public class LivingEntityStats {
|
||||
public boolean loot;
|
||||
public String name;
|
||||
public boolean visible;
|
||||
public float health;
|
||||
public short air;
|
||||
public boolean persistent;
|
||||
public boolean leashed;
|
||||
public short leash_x;
|
||||
public short leash_y;
|
||||
public short leash_z;
|
||||
public boolean equipped;
|
||||
public ItemStack hands;
|
||||
public ItemStack helmet;
|
||||
public ItemStack boots;
|
||||
public ItemStack leggings;
|
||||
public ItemStack chestplate;
|
||||
public Collection<PotionEffect> potions;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.plotsquared.bukkit.object.entity;
|
||||
|
||||
import org.bukkit.entity.AnimalTamer;
|
||||
|
||||
public class TameableStats {
|
||||
public AnimalTamer owner;
|
||||
public boolean tamed;
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
package com.plotsquared.bukkit.object.schematic;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.intellectualcrafters.jnbt.ByteTag;
|
||||
import com.intellectualcrafters.jnbt.CompoundTag;
|
||||
import com.intellectualcrafters.jnbt.ListTag;
|
||||
import com.intellectualcrafters.jnbt.ShortTag;
|
||||
import com.intellectualcrafters.jnbt.Tag;
|
||||
import com.intellectualcrafters.plot.object.schematic.ItemType;
|
||||
import com.intellectualcrafters.plot.object.schematic.PlotItem;
|
||||
import com.intellectualcrafters.plot.util.MathMan;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler.Schematic;
|
||||
|
||||
public class StateWrapper {
|
||||
|
||||
public BlockState state = null;
|
||||
public CompoundTag tag = null;
|
||||
|
||||
public StateWrapper(final BlockState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public StateWrapper(final CompoundTag tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public boolean restoreTag(final short x, final short y, final short z, final Schematic schematic) {
|
||||
if (tag == null) {
|
||||
return false;
|
||||
}
|
||||
final List<Tag> itemsTag = tag.getListTag("Items").getValue();
|
||||
final int length = itemsTag.size();
|
||||
final short[] ids = new short[length];
|
||||
final byte[] datas = new byte[length];
|
||||
final byte[] amounts = new byte[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
final Tag itemTag = itemsTag.get(i);
|
||||
final CompoundTag itemComp = (CompoundTag) itemTag;
|
||||
short id = itemComp.getShort("id");
|
||||
String idStr = itemComp.getString("id");
|
||||
if (idStr != null && !MathMan.isInteger(idStr)) {
|
||||
idStr = idStr.split(":")[0].toLowerCase();
|
||||
id = (short) ItemType.getId(idStr);
|
||||
}
|
||||
ids[i] = id;
|
||||
datas[i] = (byte) itemComp.getShort("Damage");
|
||||
amounts[i] = itemComp.getByte("Count");
|
||||
}
|
||||
if (length != 0) {
|
||||
schematic.addItem(new PlotItem(x, y, z, ids, datas, amounts));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public CompoundTag getTag() {
|
||||
if (tag != null) {
|
||||
return tag;
|
||||
}
|
||||
if (state instanceof InventoryHolder) {
|
||||
final InventoryHolder inv = (InventoryHolder) state;
|
||||
final ItemStack[] contents = inv.getInventory().getContents();
|
||||
final Map<String, Tag> values = new HashMap<>();
|
||||
values.put("Items", new ListTag("Items", CompoundTag.class, serializeInventory(contents)));
|
||||
return new CompoundTag(values);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return "Chest";
|
||||
}
|
||||
|
||||
public List<CompoundTag> serializeInventory(final ItemStack[] items) {
|
||||
final List<CompoundTag> tags = new ArrayList<>();
|
||||
for (int i = 0; i < items.length; ++i) {
|
||||
if (items[i] != null) {
|
||||
final Map<String, Tag> tagData = serializeItem(items[i]);
|
||||
tagData.put("Slot", new ByteTag("Slot", (byte) i));
|
||||
tags.add(new CompoundTag(tagData));
|
||||
}
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Move this into the sponge module!
|
||||
*
|
||||
public Map<String, Tag> serializeItem(final org.spongepowered.api.item.inventory.ItemStack item) {
|
||||
final Map<String, Tag> data = new HashMap<String, Tag>();
|
||||
|
||||
// FIXME serialize sponge item
|
||||
|
||||
return data;
|
||||
}
|
||||
*/
|
||||
|
||||
public Map<String, Tag> serializeItem(final ItemStack item) {
|
||||
final Map<String, Tag> data = new HashMap<>();
|
||||
data.put("id", new ShortTag("id", (short) item.getTypeId()));
|
||||
data.put("Damage", new ShortTag("Damage", item.getDurability()));
|
||||
data.put("Count", new ByteTag("Count", (byte) item.getAmount()));
|
||||
if (!item.getEnchantments().isEmpty()) {
|
||||
final List<CompoundTag> enchantmentList = new ArrayList<>();
|
||||
for (final Entry<Enchantment, Integer> entry : item.getEnchantments().entrySet()) {
|
||||
final Map<String, Tag> enchantment = new HashMap<>();
|
||||
enchantment.put("id", new ShortTag("id", (short) entry.getKey().getId()));
|
||||
enchantment.put("lvl", new ShortTag("lvl", entry.getValue().shortValue()));
|
||||
enchantmentList.add(new CompoundTag(enchantment));
|
||||
}
|
||||
final Map<String, Tag> auxData = new HashMap<>();
|
||||
auxData.put("ench", new ListTag("ench", CompoundTag.class, enchantmentList));
|
||||
data.put("tag", new CompoundTag("tag", auxData));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.plotsquared.bukkit.titles;
|
||||
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.util.AbstractTitle;
|
||||
import com.plotsquared.bukkit.object.BukkitPlayer;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public class DefaultTitle extends AbstractTitle {
|
||||
|
||||
@Override
|
||||
public void sendTitle(final PlotPlayer player, final String head, final String sub, final int in, final int delay, final int out) {
|
||||
try {
|
||||
final DefaultTitleManager title = new DefaultTitleManager(head, sub, in, delay, out);
|
||||
title.send(((BukkitPlayer) player).player);
|
||||
} catch (ClassNotFoundException | InvocationTargetException | SecurityException | NoSuchMethodException | InstantiationException |
|
||||
IllegalArgumentException | IllegalAccessException e) {
|
||||
AbstractTitle.TITLE_CLASS = new DefaultTitle_183();
|
||||
AbstractTitle.TITLE_CLASS.sendTitle(player, head, sub, in, delay, out);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,418 @@
|
||||
package com.plotsquared.bukkit.titles;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* [ PlotSquared DefaultTitleManager by Maxim Van de Wynckel ]
|
||||
*
|
||||
* @version 1.1.0
|
||||
* @author Maxim Van de Wynckel
|
||||
*
|
||||
*/
|
||||
public class DefaultTitleManager {
|
||||
|
||||
private static final Map<Class<?>, Class<?>> CORRESPONDING_TYPES = new HashMap<>();
|
||||
/* Title packet */
|
||||
private Class<?> packetTitle;
|
||||
/* Title packet actions ENUM */
|
||||
private Class<?> packetActions;
|
||||
/* Chat serializer */
|
||||
private Class<?> nmsChatSerializer;
|
||||
private Class<?> chatBaseComponent;
|
||||
/* Title text and color */
|
||||
private String title = "";
|
||||
private ChatColor titleColor = ChatColor.WHITE;
|
||||
/* Subtitle text and color */
|
||||
private String subtitle = "";
|
||||
private ChatColor subtitleColor = ChatColor.WHITE;
|
||||
/* Title timings */
|
||||
private int fadeInTime = -1;
|
||||
private int stayTime = -1;
|
||||
private int fadeOutTime = -1;
|
||||
private boolean ticks = false;
|
||||
|
||||
/**
|
||||
* Create a new 1.8 title
|
||||
*
|
||||
* @param title
|
||||
* Title
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
public DefaultTitleManager(final String title) throws ClassNotFoundException {
|
||||
this.title = title;
|
||||
loadClasses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new 1.8 title
|
||||
*
|
||||
* @param title
|
||||
* Title text
|
||||
* @param subtitle
|
||||
* Subtitle text
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
public DefaultTitleManager(final String title, final String subtitle) throws ClassNotFoundException {
|
||||
this.title = title;
|
||||
this.subtitle = subtitle;
|
||||
loadClasses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy 1.8 title
|
||||
*
|
||||
* @param title
|
||||
* Title
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
public DefaultTitleManager(final DefaultTitleManager title) throws ClassNotFoundException {
|
||||
// Copy title
|
||||
this.title = title.title;
|
||||
subtitle = title.subtitle;
|
||||
titleColor = title.titleColor;
|
||||
subtitleColor = title.subtitleColor;
|
||||
fadeInTime = title.fadeInTime;
|
||||
fadeOutTime = title.fadeOutTime;
|
||||
stayTime = title.stayTime;
|
||||
ticks = title.ticks;
|
||||
loadClasses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new 1.8 title
|
||||
*
|
||||
* @param title
|
||||
* Title text
|
||||
* @param subtitle
|
||||
* Subtitle text
|
||||
* @param fadeInTime
|
||||
* Fade in time
|
||||
* @param stayTime
|
||||
* Stay on screen time
|
||||
* @param fadeOutTime
|
||||
* Fade out time
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
public DefaultTitleManager(final String title, final String subtitle, final int fadeInTime, final int stayTime, final int fadeOutTime)
|
||||
throws ClassNotFoundException {
|
||||
this.title = title;
|
||||
this.subtitle = subtitle;
|
||||
this.fadeInTime = fadeInTime;
|
||||
this.stayTime = stayTime;
|
||||
this.fadeOutTime = fadeOutTime;
|
||||
loadClasses();
|
||||
}
|
||||
|
||||
private static boolean equalsTypeArray(final Class<?>[] a, final Class<?>[] o) {
|
||||
if (a.length != o.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
if (!a[i].equals(o[i]) && !a[i].isAssignableFrom(o[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load spigot and NMS classes
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
private void loadClasses() throws ClassNotFoundException {
|
||||
packetTitle = getNMSClass("PacketPlayOutTitle");
|
||||
packetActions = getNMSClass("EnumTitleAction");
|
||||
chatBaseComponent = getNMSClass("IChatBaseComponent");
|
||||
nmsChatSerializer = getNMSClass("ChatSerializer");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get title text
|
||||
*
|
||||
* @return Title text
|
||||
*/
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set title text
|
||||
*
|
||||
* @param title
|
||||
* Title
|
||||
*/
|
||||
public void setTitle(final String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subtitle text
|
||||
*
|
||||
* @return Subtitle text
|
||||
*/
|
||||
public String getSubtitle() {
|
||||
return subtitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set subtitle text
|
||||
*
|
||||
* @param subtitle
|
||||
* Subtitle text
|
||||
*/
|
||||
public void setSubtitle(final String subtitle) {
|
||||
this.subtitle = subtitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the title color
|
||||
*
|
||||
* @param color
|
||||
* Chat color
|
||||
*/
|
||||
public void setTitleColor(final ChatColor color) {
|
||||
titleColor = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the subtitle color
|
||||
*
|
||||
* @param color
|
||||
* Chat color
|
||||
*/
|
||||
public void setSubtitleColor(final ChatColor color) {
|
||||
subtitleColor = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set title fade in time
|
||||
*
|
||||
* @param time
|
||||
* Time
|
||||
*/
|
||||
public void setFadeInTime(final int time) {
|
||||
fadeInTime = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set title fade out time
|
||||
*
|
||||
* @param time
|
||||
* Time
|
||||
*/
|
||||
public void setFadeOutTime(final int time) {
|
||||
fadeOutTime = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set title stay time
|
||||
*
|
||||
* @param time
|
||||
* Time
|
||||
*/
|
||||
public void setStayTime(final int time) {
|
||||
stayTime = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set timings to ticks
|
||||
*/
|
||||
public void setTimingsToTicks() {
|
||||
ticks = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set timings to seconds
|
||||
*/
|
||||
public void setTimingsToSeconds() {
|
||||
ticks = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the title to a player
|
||||
*
|
||||
* @param player
|
||||
* Player
|
||||
* @throws InvocationTargetException
|
||||
* @throws IllegalArgumentException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public void send(final Player player)
|
||||
throws IllegalArgumentException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException,
|
||||
SecurityException {
|
||||
if (packetTitle != null) {
|
||||
// First reset previous settings
|
||||
resetTitle(player);
|
||||
// Send timings first
|
||||
final Object handle = getHandle(player);
|
||||
final Object connection = getField(handle.getClass(), "playerConnection").get(handle);
|
||||
final Object[] actions = packetActions.getEnumConstants();
|
||||
final Method sendPacket = getMethod(connection.getClass(), "sendPacket");
|
||||
Object packet = packetTitle.getConstructor(packetActions, chatBaseComponent, Integer.TYPE, Integer.TYPE, Integer.TYPE)
|
||||
.newInstance(actions[2], null, fadeInTime * (ticks ? 1 : 20),
|
||||
stayTime * (ticks ? 1 : 20), fadeOutTime * (ticks ? 1 : 20));
|
||||
// Send if set
|
||||
if (fadeInTime != -1 && fadeOutTime != -1 && stayTime != -1) {
|
||||
sendPacket.invoke(connection, packet);
|
||||
}
|
||||
// Send title
|
||||
Object serialized = getMethod(nmsChatSerializer, "a", String.class).invoke(null,
|
||||
"{text:\"" + ChatColor.translateAlternateColorCodes('&', title) + "\",color:" + titleColor.name().toLowerCase() + "}");
|
||||
packet = packetTitle.getConstructor(packetActions, chatBaseComponent).newInstance(actions[0], serialized);
|
||||
sendPacket.invoke(connection, packet);
|
||||
if (!subtitle.isEmpty()) {
|
||||
// Send subtitle if present
|
||||
serialized = getMethod(nmsChatSerializer, "a", String.class).invoke(null,
|
||||
"{text:\"" + ChatColor.translateAlternateColorCodes('&', subtitle) + "\",color:" + subtitleColor.name().toLowerCase() + "}");
|
||||
packet = packetTitle.getConstructor(packetActions, chatBaseComponent).newInstance(actions[1], serialized);
|
||||
sendPacket.invoke(connection, packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast the title to all players
|
||||
* @throws IllegalArgumentException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException,
|
||||
SecurityException
|
||||
*/
|
||||
public void broadcast()
|
||||
throws IllegalArgumentException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException,
|
||||
SecurityException {
|
||||
for (final Player p : Bukkit.getOnlinePlayers()) {
|
||||
send(p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the title
|
||||
*
|
||||
* @param player
|
||||
* Player
|
||||
* @throws IllegalAccessException
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
public void clearTitle(final Player player)
|
||||
throws IllegalArgumentException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException,
|
||||
SecurityException {
|
||||
// Send timings first
|
||||
final Object handle = getHandle(player);
|
||||
final Object connection = getField(handle.getClass(), "playerConnection").get(handle);
|
||||
final Object[] actions = packetActions.getEnumConstants();
|
||||
final Method sendPacket = getMethod(connection.getClass(), "sendPacket");
|
||||
final Object packet = packetTitle.getConstructor(packetActions, chatBaseComponent).newInstance(actions[3], null);
|
||||
sendPacket.invoke(connection, packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the title settings
|
||||
*
|
||||
* @param player
|
||||
* Player
|
||||
*/
|
||||
public void resetTitle(final Player player)
|
||||
throws IllegalArgumentException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException,
|
||||
SecurityException {
|
||||
// Send timings first
|
||||
final Object handle = getHandle(player);
|
||||
final Object connection = getField(handle.getClass(), "playerConnection").get(handle);
|
||||
final Object[] actions = packetActions.getEnumConstants();
|
||||
final Method sendPacket = getMethod(connection.getClass(), "sendPacket");
|
||||
final Object packet = packetTitle.getConstructor(packetActions, chatBaseComponent).newInstance(actions[4], null);
|
||||
sendPacket.invoke(connection, packet);
|
||||
}
|
||||
|
||||
private Class<?> getPrimitiveType(final Class<?> clazz) {
|
||||
return CORRESPONDING_TYPES.containsKey(clazz) ? CORRESPONDING_TYPES.get(clazz) : clazz;
|
||||
}
|
||||
|
||||
private Class<?>[] toPrimitiveTypeArray(final Class<?>[] classes) {
|
||||
final int a = classes != null ? classes.length : 0;
|
||||
final Class<?>[] types = new Class<?>[a];
|
||||
for (int i = 0; i < a; i++) {
|
||||
types[i] = getPrimitiveType(classes[i]);
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
private Object getHandle(final Object obj) {
|
||||
try {
|
||||
return getMethod("getHandle", obj.getClass()).invoke(obj);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Method getMethod(final String name, final Class<?> clazz, final Class<?>... paramTypes) {
|
||||
final Class<?>[] t = toPrimitiveTypeArray(paramTypes);
|
||||
for (final Method m : clazz.getMethods()) {
|
||||
final Class<?>[] types = toPrimitiveTypeArray(m.getParameterTypes());
|
||||
if (m.getName().equals(name) && equalsTypeArray(types, t)) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getVersion() {
|
||||
final String name = Bukkit.getServer().getClass().getPackage().getName();
|
||||
return name.substring(name.lastIndexOf('.') + 1) + ".";
|
||||
}
|
||||
|
||||
private Class<?> getNMSClass(final String className) throws ClassNotFoundException {
|
||||
final String fullName = "net.minecraft.server." + getVersion() + className;
|
||||
return Class.forName(fullName);
|
||||
}
|
||||
|
||||
private Field getField(final Class<?> clazz, final String name) {
|
||||
try {
|
||||
final Field field = clazz.getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} catch (SecurityException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Method getMethod(final Class<?> clazz, final String name, final Class<?>... args) {
|
||||
for (final Method m : clazz.getMethods()) {
|
||||
if (m.getName().equals(name) && (args.length == 0 || ClassListEqual(args, m.getParameterTypes()))) {
|
||||
m.setAccessible(true);
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean ClassListEqual(final Class<?>[] l1, final Class<?>[] l2) {
|
||||
if (l1.length != l2.length) {
|
||||
return false;
|
||||
}
|
||||
boolean equal = true;
|
||||
for (int i = 0; i < l1.length; i++) {
|
||||
if (l1[i] != l2[i]) {
|
||||
equal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return equal;
|
||||
}
|
||||
}
|
@ -0,0 +1,405 @@
|
||||
package com.plotsquared.bukkit.titles;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* [ PlotSquared DefaultTitleManager by Maxim Van de Wynckel ]
|
||||
*
|
||||
* @version 1.1.0
|
||||
* @author Maxim Van de Wynckel
|
||||
*
|
||||
*/
|
||||
public class DefaultTitleManager_183 {
|
||||
/* Title packet */
|
||||
private Class<?> packetTitle;
|
||||
/* Title packet actions ENUM */
|
||||
private Class<?> packetActions;
|
||||
/* Chat serializer */
|
||||
private Class<?> nmsChatSerializer;
|
||||
private Class<?> chatBaseComponent;
|
||||
/* Title text and color */
|
||||
private String title = "";
|
||||
private ChatColor titleColor = ChatColor.WHITE;
|
||||
/* Subtitle text and color */
|
||||
private String subtitle = "";
|
||||
private ChatColor subtitleColor = ChatColor.WHITE;
|
||||
/* Title timings */
|
||||
private int fadeInTime = -1;
|
||||
private int stayTime = -1;
|
||||
private int fadeOutTime = -1;
|
||||
private boolean ticks = false;
|
||||
private static final Map<Class<?>, Class<?>> CORRESPONDING_TYPES = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Create a new 1.8 title
|
||||
*
|
||||
* @param title
|
||||
* Title
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
public DefaultTitleManager_183(final String title) throws ClassNotFoundException {
|
||||
this.title = title;
|
||||
loadClasses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new 1.8 title
|
||||
*
|
||||
* @param title
|
||||
* Title text
|
||||
* @param subtitle
|
||||
* Subtitle text
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
public DefaultTitleManager_183(final String title, final String subtitle) throws ClassNotFoundException {
|
||||
this.title = title;
|
||||
this.subtitle = subtitle;
|
||||
loadClasses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy 1.8 title
|
||||
*
|
||||
* @param title
|
||||
* Title
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
public DefaultTitleManager_183(final DefaultTitleManager_183 title) throws ClassNotFoundException {
|
||||
// Copy title
|
||||
this.title = title.title;
|
||||
subtitle = title.subtitle;
|
||||
titleColor = title.titleColor;
|
||||
subtitleColor = title.subtitleColor;
|
||||
fadeInTime = title.fadeInTime;
|
||||
fadeOutTime = title.fadeOutTime;
|
||||
stayTime = title.stayTime;
|
||||
ticks = title.ticks;
|
||||
loadClasses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new 1.8 title
|
||||
*
|
||||
* @param title
|
||||
* Title text
|
||||
* @param subtitle
|
||||
* Subtitle text
|
||||
* @param fadeInTime
|
||||
* Fade in time
|
||||
* @param stayTime
|
||||
* Stay on screen time
|
||||
* @param fadeOutTime
|
||||
* Fade out time
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
public DefaultTitleManager_183(final String title, final String subtitle, final int fadeInTime, final int stayTime, final int fadeOutTime) throws ClassNotFoundException {
|
||||
this.title = title;
|
||||
this.subtitle = subtitle;
|
||||
this.fadeInTime = fadeInTime;
|
||||
this.stayTime = stayTime;
|
||||
this.fadeOutTime = fadeOutTime;
|
||||
loadClasses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load spigot and NMS classes
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
private void loadClasses() throws ClassNotFoundException {
|
||||
packetTitle = getNMSClass("PacketPlayOutTitle");
|
||||
chatBaseComponent = getNMSClass("IChatBaseComponent");
|
||||
packetActions = getNMSClass("PacketPlayOutTitle$EnumTitleAction");
|
||||
nmsChatSerializer = getNMSClass("IChatBaseComponent$ChatSerializer");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set title text
|
||||
*
|
||||
* @param title
|
||||
* Title
|
||||
*/
|
||||
public void setTitle(final String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get title text
|
||||
*
|
||||
* @return Title text
|
||||
*/
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set subtitle text
|
||||
*
|
||||
* @param subtitle
|
||||
* Subtitle text
|
||||
*/
|
||||
public void setSubtitle(final String subtitle) {
|
||||
this.subtitle = subtitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subtitle text
|
||||
*
|
||||
* @return Subtitle text
|
||||
*/
|
||||
public String getSubtitle() {
|
||||
return subtitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the title color
|
||||
*
|
||||
* @param color
|
||||
* Chat color
|
||||
*/
|
||||
public void setTitleColor(final ChatColor color) {
|
||||
titleColor = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the subtitle color
|
||||
*
|
||||
* @param color
|
||||
* Chat color
|
||||
*/
|
||||
public void setSubtitleColor(final ChatColor color) {
|
||||
subtitleColor = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set title fade in time
|
||||
*
|
||||
* @param time
|
||||
* Time
|
||||
*/
|
||||
public void setFadeInTime(final int time) {
|
||||
fadeInTime = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set title fade out time
|
||||
*
|
||||
* @param time
|
||||
* Time
|
||||
*/
|
||||
public void setFadeOutTime(final int time) {
|
||||
fadeOutTime = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set title stay time
|
||||
*
|
||||
* @param time
|
||||
* Time
|
||||
*/
|
||||
public void setStayTime(final int time) {
|
||||
stayTime = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set timings to ticks
|
||||
*/
|
||||
public void setTimingsToTicks() {
|
||||
ticks = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set timings to seconds
|
||||
*/
|
||||
public void setTimingsToSeconds() {
|
||||
ticks = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the title to a player
|
||||
*
|
||||
* @param player
|
||||
* Player
|
||||
* @throws InvocationTargetException
|
||||
* @throws IllegalArgumentException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public void send(final Player player) throws Exception {
|
||||
if (packetTitle != null) {
|
||||
// First reset previous settings
|
||||
resetTitle(player);
|
||||
// Send timings first
|
||||
final Object handle = getHandle(player);
|
||||
final Object connection = getField(handle.getClass(), "playerConnection").get(handle);
|
||||
final Object[] actions = packetActions.getEnumConstants();
|
||||
final Method sendPacket = getMethod(connection.getClass(), "sendPacket");
|
||||
Object packet = packetTitle.getConstructor(packetActions, chatBaseComponent, Integer.TYPE, Integer.TYPE, Integer.TYPE).newInstance(actions[2], null, fadeInTime * (ticks ? 1 : 20),
|
||||
stayTime * (ticks ? 1 : 20), fadeOutTime * (ticks ? 1 : 20));
|
||||
// Send if set
|
||||
if ((fadeInTime != -1) && (fadeOutTime != -1) && (stayTime != -1)) {
|
||||
sendPacket.invoke(connection, packet);
|
||||
}
|
||||
// Send title
|
||||
Object serialized = getMethod(nmsChatSerializer, "a", String.class).invoke(null,
|
||||
"{text:\"" + ChatColor.translateAlternateColorCodes('&', title) + "\",color:" + titleColor.name().toLowerCase() + "}");
|
||||
packet = packetTitle.getConstructor(packetActions, chatBaseComponent).newInstance(actions[0], serialized);
|
||||
sendPacket.invoke(connection, packet);
|
||||
if (!subtitle.isEmpty()) {
|
||||
// Send subtitle if present
|
||||
serialized = getMethod(nmsChatSerializer, "a", String.class).invoke(null,
|
||||
"{text:\"" + ChatColor.translateAlternateColorCodes('&', subtitle) + "\",color:" + subtitleColor.name().toLowerCase() + "}");
|
||||
packet = packetTitle.getConstructor(packetActions, chatBaseComponent).newInstance(actions[1], serialized);
|
||||
sendPacket.invoke(connection, packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast the title to all players
|
||||
* @throws Exception
|
||||
*/
|
||||
public void broadcast() throws Exception {
|
||||
for (final Player p : Bukkit.getOnlinePlayers()) {
|
||||
send(p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the title
|
||||
*
|
||||
* @param player
|
||||
* Player
|
||||
* @throws IllegalAccessException
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
public void clearTitle(final Player player) throws Exception {
|
||||
// Send timings first
|
||||
final Object handle = getHandle(player);
|
||||
final Object connection = getField(handle.getClass(), "playerConnection").get(handle);
|
||||
final Object[] actions = packetActions.getEnumConstants();
|
||||
final Method sendPacket = getMethod(connection.getClass(), "sendPacket");
|
||||
final Object packet = packetTitle.getConstructor(packetActions, chatBaseComponent).newInstance(actions[3], null);
|
||||
sendPacket.invoke(connection, packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the title settings
|
||||
*
|
||||
* @param player
|
||||
* Player
|
||||
* @throws SecurityException
|
||||
* @throws NoSuchMethodException
|
||||
* @throws InvocationTargetException
|
||||
* @throws IllegalArgumentException
|
||||
* @throws IllegalAccessException
|
||||
* @throws InstantiationException
|
||||
*/
|
||||
public void resetTitle(final Player player) throws Exception {
|
||||
// Send timings first
|
||||
final Object handle = getHandle(player);
|
||||
final Object connection = getField(handle.getClass(), "playerConnection").get(handle);
|
||||
final Object[] actions = packetActions.getEnumConstants();
|
||||
final Method sendPacket = getMethod(connection.getClass(), "sendPacket");
|
||||
final Object packet = packetTitle.getConstructor(packetActions, chatBaseComponent).newInstance(actions[4], null);
|
||||
sendPacket.invoke(connection, packet);
|
||||
}
|
||||
|
||||
private Class<?> getPrimitiveType(final Class<?> clazz) {
|
||||
return CORRESPONDING_TYPES.containsKey(clazz) ? CORRESPONDING_TYPES.get(clazz) : clazz;
|
||||
}
|
||||
|
||||
private Class<?>[] toPrimitiveTypeArray(final Class<?>[] classes) {
|
||||
final int a = classes != null ? classes.length : 0;
|
||||
final Class<?>[] types = new Class<?>[a];
|
||||
for (int i = 0; i < a; i++) {
|
||||
types[i] = getPrimitiveType(classes[i]);
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
private static boolean equalsTypeArray(final Class<?>[] a, final Class<?>[] o) {
|
||||
if (a.length != o.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
if (!a[i].equals(o[i]) && !a[i].isAssignableFrom(o[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private Object getHandle(final Object obj) {
|
||||
try {
|
||||
return getMethod("getHandle", obj.getClass()).invoke(obj);
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Method getMethod(final String name, final Class<?> clazz, final Class<?>... paramTypes) {
|
||||
final Class<?>[] t = toPrimitiveTypeArray(paramTypes);
|
||||
for (final Method m : clazz.getMethods()) {
|
||||
final Class<?>[] types = toPrimitiveTypeArray(m.getParameterTypes());
|
||||
if (m.getName().equals(name) && equalsTypeArray(types, t)) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getVersion() {
|
||||
final String name = Bukkit.getServer().getClass().getPackage().getName();
|
||||
final String version = name.substring(name.lastIndexOf('.') + 1) + ".";
|
||||
return version;
|
||||
}
|
||||
|
||||
private Class<?> getNMSClass(final String className) throws ClassNotFoundException {
|
||||
final String fullName = "net.minecraft.server." + getVersion() + className;
|
||||
return Class.forName(fullName);
|
||||
}
|
||||
|
||||
private Field getField(final Class<?> clazz, final String name) {
|
||||
try {
|
||||
final Field field = clazz.getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Method getMethod(final Class<?> clazz, final String name, final Class<?>... args) {
|
||||
for (final Method m : clazz.getMethods()) {
|
||||
if (m.getName().equals(name) && ((args.length == 0) || ClassListEqual(args, m.getParameterTypes()))) {
|
||||
m.setAccessible(true);
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean ClassListEqual(final Class<?>[] l1, final Class<?>[] l2) {
|
||||
if (l1.length != l2.length) {
|
||||
return false;
|
||||
}
|
||||
boolean equal = true;
|
||||
for (int i = 0; i < l1.length; i++) {
|
||||
if (l1[i] != l2[i]) {
|
||||
equal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return equal;
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.plotsquared.bukkit.titles;
|
||||
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.util.AbstractTitle;
|
||||
import com.plotsquared.bukkit.object.BukkitPlayer;
|
||||
|
||||
public class DefaultTitle_183 extends AbstractTitle {
|
||||
@Override
|
||||
public void sendTitle(final PlotPlayer player, final String head, final String sub, final int in, final int delay, final int out) {
|
||||
try {
|
||||
final DefaultTitleManager_183 title = new DefaultTitleManager_183(head, sub, in, delay, out);
|
||||
title.send(((BukkitPlayer) player).player);
|
||||
} catch (final Throwable e) {
|
||||
AbstractTitle.TITLE_CLASS = new HackTitle();
|
||||
AbstractTitle.TITLE_CLASS.sendTitle(player, head, sub, in, delay, out);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package com.plotsquared.bukkit.titles;
|
||||
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.config.Settings;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.util.AbstractTitle;
|
||||
import com.plotsquared.bukkit.object.BukkitPlayer;
|
||||
|
||||
public class HackTitle extends AbstractTitle {
|
||||
@Override
|
||||
public void sendTitle(final PlotPlayer player, final String head, final String sub, final int in, final int delay, final int out) {
|
||||
try {
|
||||
final HackTitleManager title = new HackTitleManager(head, sub, in, delay, out);
|
||||
title.send(((BukkitPlayer) player).player);
|
||||
} catch (Exception e) {
|
||||
PS.debug("&cYour server version does not support titles!");
|
||||
Settings.TITLES = false;
|
||||
AbstractTitle.TITLE_CLASS = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,443 @@
|
||||
package com.plotsquared.bukkit.titles;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Minecraft 1.8 Title
|
||||
*
|
||||
* @version 1.0.4
|
||||
* @author Maxim Van de Wynckel
|
||||
*/
|
||||
public class HackTitleManager {
|
||||
/* Title packet */
|
||||
private Class<?> packetTitle;
|
||||
/* Title packet actions ENUM */
|
||||
private Class<?> packetActions;
|
||||
/* Chat serializer */
|
||||
private Class<?> nmsChatSerializer;
|
||||
/* Title text and color */
|
||||
private String title = "";
|
||||
private ChatColor titleColor = ChatColor.WHITE;
|
||||
/* Subtitle text and color */
|
||||
private String subtitle = "";
|
||||
private ChatColor subtitleColor = ChatColor.WHITE;
|
||||
/* Title timings */
|
||||
private int fadeInTime = -1;
|
||||
private int stayTime = -1;
|
||||
private int fadeOutTime = -1;
|
||||
private boolean ticks = false;
|
||||
private static final Map<Class<?>, Class<?>> CORRESPONDING_TYPES = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Create a new 1.8 title
|
||||
*
|
||||
* @param title
|
||||
* Title
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
public HackTitleManager(final String title) throws ClassNotFoundException {
|
||||
this.title = title;
|
||||
loadClasses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new 1.8 title
|
||||
*
|
||||
* @param title
|
||||
* Title text
|
||||
* @param subtitle
|
||||
* Subtitle text
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
public HackTitleManager(final String title, final String subtitle) throws ClassNotFoundException {
|
||||
this.title = title;
|
||||
this.subtitle = subtitle;
|
||||
loadClasses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy 1.8 title
|
||||
*
|
||||
* @param title
|
||||
* Title
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
public HackTitleManager(final HackTitleManager title) throws ClassNotFoundException {
|
||||
// Copy title
|
||||
this.title = title.title;
|
||||
subtitle = title.subtitle;
|
||||
titleColor = title.titleColor;
|
||||
subtitleColor = title.subtitleColor;
|
||||
fadeInTime = title.fadeInTime;
|
||||
fadeOutTime = title.fadeOutTime;
|
||||
stayTime = title.stayTime;
|
||||
ticks = title.ticks;
|
||||
loadClasses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new 1.8 title
|
||||
*
|
||||
* @param title
|
||||
* Title text
|
||||
* @param subtitle
|
||||
* Subtitle text
|
||||
* @param fadeInTime
|
||||
* Fade in time
|
||||
* @param stayTime
|
||||
* Stay on screen time
|
||||
* @param fadeOutTime
|
||||
* Fade out time
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
public HackTitleManager(final String title, final String subtitle, final int fadeInTime, final int stayTime, final int fadeOutTime) throws ClassNotFoundException {
|
||||
this.title = title;
|
||||
this.subtitle = subtitle;
|
||||
this.fadeInTime = fadeInTime;
|
||||
this.stayTime = stayTime;
|
||||
this.fadeOutTime = fadeOutTime;
|
||||
loadClasses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load spigot and NMS classes
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
private void loadClasses() throws ClassNotFoundException {
|
||||
packetTitle = getClass("org.spigotmc.ProtocolInjector$PacketTitle");
|
||||
packetActions = getClass("org.spigotmc.ProtocolInjector$PacketTitle$Action");
|
||||
nmsChatSerializer = getNMSClass("ChatSerializer");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set title text
|
||||
*
|
||||
* @param title
|
||||
* Title
|
||||
*/
|
||||
public void setTitle(final String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get title text
|
||||
*
|
||||
* @return Title text
|
||||
*/
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set subtitle text
|
||||
*
|
||||
* @param subtitle
|
||||
* Subtitle text
|
||||
*/
|
||||
public void setSubtitle(final String subtitle) {
|
||||
this.subtitle = subtitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subtitle text
|
||||
*
|
||||
* @return Subtitle text
|
||||
*/
|
||||
public String getSubtitle() {
|
||||
return subtitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the title color
|
||||
*
|
||||
* @param color
|
||||
* Chat color
|
||||
*/
|
||||
public void setTitleColor(final ChatColor color) {
|
||||
titleColor = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the subtitle color
|
||||
*
|
||||
* @param color
|
||||
* Chat color
|
||||
*/
|
||||
public void setSubtitleColor(final ChatColor color) {
|
||||
subtitleColor = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set title fade in time
|
||||
*
|
||||
* @param time
|
||||
* Time
|
||||
*/
|
||||
public void setFadeInTime(final int time) {
|
||||
fadeInTime = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set title fade out time
|
||||
*
|
||||
* @param time
|
||||
* Time
|
||||
*/
|
||||
public void setFadeOutTime(final int time) {
|
||||
fadeOutTime = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set title stay time
|
||||
*
|
||||
* @param time
|
||||
* Time
|
||||
*/
|
||||
public void setStayTime(final int time) {
|
||||
stayTime = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set timings to ticks
|
||||
*/
|
||||
public void setTimingsToTicks() {
|
||||
ticks = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set timings to seconds
|
||||
*/
|
||||
public void setTimingsToSeconds() {
|
||||
ticks = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the title to a player
|
||||
*
|
||||
* @param player
|
||||
* Player
|
||||
*/
|
||||
public void send(final Player player) throws Exception {
|
||||
if ((getProtocolVersion(player) >= 47) && isSpigot() && (packetTitle != null)) {
|
||||
// First reset previous settings
|
||||
resetTitle(player);
|
||||
// Send timings first
|
||||
final Object handle = getHandle(player);
|
||||
final Object connection = getField(handle.getClass(), "playerConnection").get(handle);
|
||||
final Object[] actions = packetActions.getEnumConstants();
|
||||
final Method sendPacket = getMethod(connection.getClass(), "sendPacket");
|
||||
Object packet = packetTitle.getConstructor(packetActions, Integer.TYPE, Integer.TYPE, Integer.TYPE).newInstance(actions[2], fadeInTime * (ticks ? 1 : 20), stayTime * (ticks ? 1 : 20),
|
||||
fadeOutTime * (ticks ? 1 : 20));
|
||||
// Send if set
|
||||
if ((fadeInTime != -1) && (fadeOutTime != -1) && (stayTime != -1)) {
|
||||
sendPacket.invoke(connection, packet);
|
||||
}
|
||||
// Send title
|
||||
Object serialized = getMethod(nmsChatSerializer, "a", String.class).invoke(null,
|
||||
"{text:\"" + ChatColor.translateAlternateColorCodes('&', title) + "\",color:" + titleColor.name().toLowerCase() + "}");
|
||||
packet = packetTitle.getConstructor(packetActions, getNMSClass("IChatBaseComponent")).newInstance(actions[0], serialized);
|
||||
sendPacket.invoke(connection, packet);
|
||||
if (!subtitle.isEmpty()) {
|
||||
// Send subtitle if present
|
||||
serialized = getMethod(nmsChatSerializer, "a", String.class).invoke(null,
|
||||
"{text:\"" + ChatColor.translateAlternateColorCodes('&', subtitle) + "\",color:" + subtitleColor.name().toLowerCase() + "}");
|
||||
packet = packetTitle.getConstructor(packetActions, getNMSClass("IChatBaseComponent")).newInstance(actions[1], serialized);
|
||||
sendPacket.invoke(connection, packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast the title to all players
|
||||
*/
|
||||
public void broadcast() throws Exception {
|
||||
for (final Player p : Bukkit.getOnlinePlayers()) {
|
||||
send(p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the title
|
||||
*
|
||||
* @param player
|
||||
* Player
|
||||
* @throws Exception
|
||||
*/
|
||||
public void clearTitle(final Player player) throws Exception {
|
||||
if ((getProtocolVersion(player) >= 47) && isSpigot()) {
|
||||
// Send timings first
|
||||
final Object handle = getHandle(player);
|
||||
final Object connection = getField(handle.getClass(), "playerConnection").get(handle);
|
||||
final Object[] actions = packetActions.getEnumConstants();
|
||||
final Method sendPacket = getMethod(connection.getClass(), "sendPacket");
|
||||
final Object packet = packetTitle.getConstructor(packetActions).newInstance(actions[3]);
|
||||
sendPacket.invoke(connection, packet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the title settings
|
||||
*
|
||||
* @param player
|
||||
* Player
|
||||
* @throws Exception
|
||||
*/
|
||||
public void resetTitle(final Player player) throws Exception {
|
||||
if ((getProtocolVersion(player) >= 47) && isSpigot()) {
|
||||
// Send timings first
|
||||
final Object handle = getHandle(player);
|
||||
final Object connection = getField(handle.getClass(), "playerConnection").get(handle);
|
||||
final Object[] actions = packetActions.getEnumConstants();
|
||||
final Method sendPacket = getMethod(connection.getClass(), "sendPacket");
|
||||
final Object packet = packetTitle.getConstructor(packetActions).newInstance(actions[4]);
|
||||
sendPacket.invoke(connection, packet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the protocol version of the player
|
||||
*
|
||||
* @param player
|
||||
* Player
|
||||
* @return Protocol version
|
||||
* @throws Exception
|
||||
*/
|
||||
private int getProtocolVersion(final Player player) throws Exception {
|
||||
final Object handle = getHandle(player);
|
||||
final Object connection = getField(handle.getClass(), "playerConnection").get(handle);
|
||||
final Object networkManager = getValue("networkManager", connection);
|
||||
return (Integer) getMethod("getVersion", networkManager.getClass()).invoke(networkManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if running spigot
|
||||
*
|
||||
* @return Spigot
|
||||
*/
|
||||
private boolean isSpigot() {
|
||||
return Bukkit.getVersion().contains("Spigot");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get class by url
|
||||
*
|
||||
* @param namespace
|
||||
* Namespace url
|
||||
* @return Class
|
||||
*/
|
||||
private Class<?> getClass(final String namespace) {
|
||||
try {
|
||||
return Class.forName(namespace);
|
||||
} catch (ClassNotFoundException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Field getField(final String name, final Class<?> clazz) throws Exception {
|
||||
return clazz.getDeclaredField(name);
|
||||
}
|
||||
|
||||
private Object getValue(final String name, final Object obj) throws Exception {
|
||||
final Field f = getField(name, obj.getClass());
|
||||
f.setAccessible(true);
|
||||
return f.get(obj);
|
||||
}
|
||||
|
||||
private Class<?> getPrimitiveType(final Class<?> clazz) {
|
||||
return CORRESPONDING_TYPES.containsKey(clazz) ? CORRESPONDING_TYPES.get(clazz) : clazz;
|
||||
}
|
||||
|
||||
private Class<?>[] toPrimitiveTypeArray(final Class<?>[] classes) {
|
||||
final int a = classes != null ? classes.length : 0;
|
||||
final Class<?>[] types = new Class<?>[a];
|
||||
for (int i = 0; i < a; i++) {
|
||||
types[i] = getPrimitiveType(classes[i]);
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
private static boolean equalsTypeArray(final Class<?>[] a, final Class<?>[] o) {
|
||||
if (a.length != o.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
if (!a[i].equals(o[i]) && !a[i].isAssignableFrom(o[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private Object getHandle(final Object obj) {
|
||||
try {
|
||||
return getMethod("getHandle", obj.getClass()).invoke(obj);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Method getMethod(final String name, final Class<?> clazz, final Class<?>... paramTypes) {
|
||||
final Class<?>[] t = toPrimitiveTypeArray(paramTypes);
|
||||
for (final Method m : clazz.getMethods()) {
|
||||
final Class<?>[] types = toPrimitiveTypeArray(m.getParameterTypes());
|
||||
if (m.getName().equals(name) && equalsTypeArray(types, t)) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getVersion() {
|
||||
final String name = Bukkit.getServer().getClass().getPackage().getName();
|
||||
return name.substring(name.lastIndexOf('.') + 1) + ".";
|
||||
}
|
||||
|
||||
private Class<?> getNMSClass(final String className) throws ClassNotFoundException {
|
||||
final String fullName = "net.minecraft.server." + getVersion() + className;
|
||||
return Class.forName(fullName);
|
||||
}
|
||||
|
||||
private Field getField(final Class<?> clazz, final String name) {
|
||||
try {
|
||||
final Field field = clazz.getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
} catch (SecurityException | NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Method getMethod(final Class<?> clazz, final String name, final Class<?>... args) {
|
||||
for (final Method m : clazz.getMethods()) {
|
||||
if (m.getName().equals(name) && ((args.length == 0) || ClassListEqual(args, m.getParameterTypes()))) {
|
||||
m.setAccessible(true);
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean ClassListEqual(final Class<?>[] l1, final Class<?>[] l2) {
|
||||
if (l1.length != l2.length) {
|
||||
return false;
|
||||
}
|
||||
boolean equal = true;
|
||||
for (int i = 0; i < l1.length; i++) {
|
||||
if (l1[i] != l2[i]) {
|
||||
equal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return equal;
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package com.plotsquared.bukkit.uuid;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
import com.intellectualcrafters.plot.object.OfflinePlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.uuid.UUIDWrapper;
|
||||
import com.plotsquared.bukkit.object.BukkitOfflinePlayer;
|
||||
import com.plotsquared.bukkit.object.BukkitPlayer;
|
||||
|
||||
public class DefaultUUIDWrapper extends UUIDWrapper {
|
||||
@Override
|
||||
public UUID getUUID(final PlotPlayer player) {
|
||||
return ((BukkitPlayer) player).player.getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(final OfflinePlotPlayer player) {
|
||||
return player.getUUID();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflinePlotPlayer getOfflinePlayer(final UUID uuid) {
|
||||
return new BukkitOfflinePlayer(Bukkit.getOfflinePlayer(uuid));
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(final String name) {
|
||||
return Bukkit.getOfflinePlayer(name).getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflinePlotPlayer[] getOfflinePlayers() {
|
||||
final OfflinePlayer[] ops = Bukkit.getOfflinePlayers();
|
||||
final BukkitOfflinePlayer[] toReturn = new BukkitOfflinePlayer[ops.length];
|
||||
for (int i = 0; i < ops.length; i++) {
|
||||
toReturn[i] = new BukkitOfflinePlayer(ops[i]);
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflinePlotPlayer getOfflinePlayer(String name) {
|
||||
return new BukkitOfflinePlayer(Bukkit.getOfflinePlayer(name));
|
||||
}
|
||||
}
|
@ -0,0 +1,233 @@
|
||||
package com.plotsquared.bukkit.uuid;
|
||||
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.io.ByteSource;
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.config.C;
|
||||
import com.intellectualcrafters.plot.config.Settings;
|
||||
import com.intellectualcrafters.plot.database.DBFunc;
|
||||
import com.intellectualcrafters.plot.object.OfflinePlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.RunnableVal;
|
||||
import com.intellectualcrafters.plot.object.StringWrapper;
|
||||
import com.intellectualcrafters.plot.util.ExpireManager;
|
||||
import com.intellectualcrafters.plot.util.StringMan;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandler;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandlerImplementation;
|
||||
import com.intellectualcrafters.plot.uuid.UUIDWrapper;
|
||||
import com.plotsquared.bukkit.util.NbtFactory;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class FileUUIDHandler extends UUIDHandlerImplementation {
|
||||
|
||||
public FileUUIDHandler(final UUIDWrapper wrapper) {
|
||||
super(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startCaching(final Runnable whenDone) {
|
||||
return super.startCaching(whenDone) && cache(whenDone);
|
||||
}
|
||||
|
||||
public boolean cache(final Runnable whenDone) {
|
||||
final File container = Bukkit.getWorldContainer();
|
||||
final List<World> worlds = Bukkit.getWorlds();
|
||||
final String world;
|
||||
if (worlds.isEmpty()) {
|
||||
world = "world";
|
||||
} else {
|
||||
world = worlds.get(0).getName();
|
||||
}
|
||||
TaskManager.runTaskAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PS.debug(C.PREFIX.s() + "&6Starting player data caching for: " + world);
|
||||
final File uuidfile = new File(PS.get().IMP.getDirectory(), "uuids.txt");
|
||||
if (uuidfile.exists()) {
|
||||
try {
|
||||
final List<String> lines = Files.readAllLines(uuidfile.toPath(), StandardCharsets.UTF_8);
|
||||
for (String line : lines) {
|
||||
try {
|
||||
line = line.trim();
|
||||
if (line.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
line = line.replaceAll("[\\|][0-9]+[\\|][0-9]+[\\|]", "");
|
||||
final String[] split = line.split("\\|");
|
||||
final String name = split[0];
|
||||
if ((name.isEmpty()) || (name.length() > 16) || !StringMan.isAlphanumericUnd(name)) {
|
||||
continue;
|
||||
}
|
||||
final UUID uuid = uuidWrapper.getUUID(name);
|
||||
if (uuid == null) {
|
||||
continue;
|
||||
}
|
||||
UUIDHandler.add(new StringWrapper(name), uuid);
|
||||
} catch (final Exception e2) {
|
||||
e2.printStackTrace();
|
||||
}
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (Settings.TWIN_MODE_UUID) {
|
||||
final HashBiMap<StringWrapper, UUID> toAdd = HashBiMap.create(new HashMap<StringWrapper, UUID>());
|
||||
toAdd.put(new StringWrapper("*"), DBFunc.everyone);
|
||||
final HashSet<UUID> all = UUIDHandler.getAllUUIDS();
|
||||
PS.debug("&aFast mode UUID caching enabled!");
|
||||
final File playerdataFolder = new File(container, world + File.separator + "playerdata");
|
||||
final String[] dat = playerdataFolder.list(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(final File f, final String s) {
|
||||
return s.endsWith(".dat");
|
||||
}
|
||||
});
|
||||
final boolean check = all.isEmpty();
|
||||
if (dat != null) {
|
||||
for (final String current : dat) {
|
||||
final String s = current.replaceAll(".dat$", "");
|
||||
try {
|
||||
final UUID uuid = UUID.fromString(s);
|
||||
if (check || all.remove(uuid)) {
|
||||
final File file = new File(playerdataFolder + File.separator + current);
|
||||
final ByteSource is = com.google.common.io.Files.asByteSource(file);
|
||||
final NbtFactory.NbtCompound compound = NbtFactory.fromStream(is, NbtFactory.StreamOptions.GZIP_COMPRESSION);
|
||||
final NbtFactory.NbtCompound bukkit = (NbtFactory.NbtCompound) compound.get("bukkit");
|
||||
final String name = (String) bukkit.get("lastKnownName");
|
||||
final long last = (long) bukkit.get("lastPlayed");
|
||||
ExpireManager.dates.put(uuid, last);
|
||||
toAdd.put(new StringWrapper(name), uuid);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
PS.debug(C.PREFIX.s() + "Invalid playerdata: " + current);
|
||||
}
|
||||
}
|
||||
}
|
||||
add(toAdd);
|
||||
if (all.isEmpty()) {
|
||||
if (whenDone != null) {
|
||||
whenDone.run();
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
PS.debug("Failed to cache: " + all.size() + " uuids - slowly processing all files");
|
||||
}
|
||||
}
|
||||
final HashBiMap<StringWrapper, UUID> toAdd = HashBiMap.create(new HashMap<StringWrapper, UUID>());
|
||||
toAdd.put(new StringWrapper("*"), DBFunc.everyone);
|
||||
final HashSet<String> worlds = new HashSet<>();
|
||||
worlds.add(world);
|
||||
worlds.add("world");
|
||||
final HashSet<UUID> uuids = new HashSet<>();
|
||||
final HashSet<String> names = new HashSet<>();
|
||||
File playerdataFolder = null;
|
||||
for (final String worldname : worlds) {
|
||||
// Getting UUIDs
|
||||
playerdataFolder = new File(container, worldname + File.separator + "playerdata");
|
||||
String[] dat = playerdataFolder.list(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(final File f, final String s) {
|
||||
return s.endsWith(".dat");
|
||||
}
|
||||
});
|
||||
if ((dat != null) && (dat.length != 0)) {
|
||||
for (final String current : dat) {
|
||||
final String s = current.replaceAll(".dat$", "");
|
||||
try {
|
||||
final UUID uuid = UUID.fromString(s);
|
||||
uuids.add(uuid);
|
||||
} catch (final Exception e) {
|
||||
PS.debug(C.PREFIX.s() + "Invalid playerdata: " + current);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Getting names
|
||||
final File playersFolder = new File(worldname + File.separator + "players");
|
||||
dat = playersFolder.list(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(final File f, final String s) {
|
||||
return s.endsWith(".dat");
|
||||
}
|
||||
});
|
||||
if ((dat != null) && (dat.length != 0)) {
|
||||
for (final String current : dat) {
|
||||
names.add(current.replaceAll(".dat$", ""));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (UUID uuid : uuids) {
|
||||
try {
|
||||
final File file = new File(playerdataFolder + File.separator + uuid.toString() + ".dat");
|
||||
final ByteSource is = com.google.common.io.Files.asByteSource(file);
|
||||
final NbtFactory.NbtCompound compound = NbtFactory.fromStream(is, NbtFactory.StreamOptions.GZIP_COMPRESSION);
|
||||
final NbtFactory.NbtCompound bukkit = (NbtFactory.NbtCompound) compound.get("bukkit");
|
||||
final String name = (String) bukkit.get("lastKnownName");
|
||||
final long last = (long) bukkit.get("lastPlayed");
|
||||
if (Settings.OFFLINE_MODE) {
|
||||
if (Settings.UUID_LOWERCASE && !name.toLowerCase().equals(name)) {
|
||||
uuid = uuidWrapper.getUUID(name);
|
||||
} else {
|
||||
final long most = (long) compound.get("UUIDMost");
|
||||
final long least = (long) compound.get("UUIDLeast");
|
||||
uuid = new UUID(most, least);
|
||||
}
|
||||
}
|
||||
ExpireManager.dates.put(uuid, last);
|
||||
toAdd.put(new StringWrapper(name), uuid);
|
||||
} catch (final Throwable e) {
|
||||
PS.debug(C.PREFIX.s() + "&6Invalid playerdata: " + uuid.toString() + ".dat");
|
||||
}
|
||||
}
|
||||
for (final String name : names) {
|
||||
final UUID uuid = uuidWrapper.getUUID(name);
|
||||
final StringWrapper nameWrap = new StringWrapper(name);
|
||||
toAdd.put(nameWrap, uuid);
|
||||
}
|
||||
|
||||
if (getUUIDMap().isEmpty()) {
|
||||
for (final OfflinePlotPlayer op : uuidWrapper.getOfflinePlayers()) {
|
||||
final long last = op.getLastPlayed();
|
||||
if (last != 0) {
|
||||
final String name = op.getName();
|
||||
final StringWrapper wrap = new StringWrapper(name);
|
||||
final UUID uuid = uuidWrapper.getUUID(op);
|
||||
toAdd.put(wrap, uuid);
|
||||
ExpireManager.dates.put(uuid, last);
|
||||
}
|
||||
}
|
||||
}
|
||||
add(toAdd);
|
||||
if (whenDone != null) {
|
||||
whenDone.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchUUID(final String name, final RunnableVal<UUID> ifFetch) {
|
||||
TaskManager.runTaskAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ifFetch.value = uuidWrapper.getUUID(name);
|
||||
TaskManager.runTask(ifFetch);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
package com.plotsquared.bukkit.uuid;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.object.OfflinePlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.StringWrapper;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandler;
|
||||
import com.plotsquared.bukkit.object.BukkitOfflinePlayer;
|
||||
|
||||
public class LowerOfflineUUIDWrapper extends OfflineUUIDWrapper {
|
||||
private Method getOnline = null;
|
||||
private final Object[] arg = new Object[0];
|
||||
|
||||
public LowerOfflineUUIDWrapper() {
|
||||
try {
|
||||
getOnline = Server.class.getMethod("getOnlinePlayers");
|
||||
} catch (final NoSuchMethodException | SecurityException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(final PlotPlayer player) {
|
||||
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getName().toLowerCase()).getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(final OfflinePlotPlayer player) {
|
||||
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getName().toLowerCase()).getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(final OfflinePlayer player) {
|
||||
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getName().toLowerCase()).getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflinePlotPlayer getOfflinePlayer(final UUID uuid) {
|
||||
final BiMap<UUID, StringWrapper> map = UUIDHandler.getUuidMap().inverse();
|
||||
String name;
|
||||
try {
|
||||
name = map.get(uuid).value;
|
||||
} catch (final NullPointerException e) {
|
||||
name = null;
|
||||
}
|
||||
if (name != null) {
|
||||
final OfflinePlayer op = Bukkit.getOfflinePlayer(name);
|
||||
if (op.hasPlayedBefore()) {
|
||||
return new BukkitOfflinePlayer(op);
|
||||
}
|
||||
}
|
||||
for (final OfflinePlayer player : Bukkit.getOfflinePlayers()) {
|
||||
if (getUUID(player).equals(uuid)) {
|
||||
return new BukkitOfflinePlayer(player);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player[] getOnlinePlayers() {
|
||||
if (getOnline == null) {
|
||||
Collection<? extends Player> onlinePlayers = Bukkit.getOnlinePlayers();
|
||||
return onlinePlayers.toArray(new Player[onlinePlayers.size()]);
|
||||
}
|
||||
try {
|
||||
final Object players = getOnline.invoke(Bukkit.getServer(), arg);
|
||||
if (players instanceof Player[]) {
|
||||
return (Player[]) players;
|
||||
} else {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Collection<? extends Player> p = (Collection<? extends Player>) players;
|
||||
return p.toArray(new Player[p.size()]);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
PS.debug("Failed to resolve online players");
|
||||
getOnline = null;
|
||||
Collection<? extends Player> onlinePlayers = Bukkit.getOnlinePlayers();
|
||||
return onlinePlayers.toArray(new Player[onlinePlayers.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(final String name) {
|
||||
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + name.toLowerCase()).getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflinePlotPlayer[] getOfflinePlayers() {
|
||||
final OfflinePlayer[] ops = Bukkit.getOfflinePlayers();
|
||||
final BukkitOfflinePlayer[] toReturn = new BukkitOfflinePlayer[ops.length];
|
||||
for (int i = 0; i < ops.length; i++) {
|
||||
toReturn[i] = new BukkitOfflinePlayer(ops[i]);
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
package com.plotsquared.bukkit.uuid;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.object.OfflinePlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.StringWrapper;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandler;
|
||||
import com.intellectualcrafters.plot.uuid.UUIDWrapper;
|
||||
import com.plotsquared.bukkit.object.BukkitOfflinePlayer;
|
||||
|
||||
public class OfflineUUIDWrapper extends UUIDWrapper {
|
||||
private Method getOnline = null;
|
||||
private final Object[] arg = new Object[0];
|
||||
|
||||
public OfflineUUIDWrapper() {
|
||||
try {
|
||||
getOnline = Server.class.getMethod("getOnlinePlayers");
|
||||
} catch (final NoSuchMethodException | SecurityException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(final PlotPlayer player) {
|
||||
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(final OfflinePlotPlayer player) {
|
||||
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
public UUID getUUID(final OfflinePlayer player) {
|
||||
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflinePlotPlayer getOfflinePlayer(final UUID uuid) {
|
||||
final BiMap<UUID, StringWrapper> map = UUIDHandler.getUuidMap().inverse();
|
||||
String name;
|
||||
try {
|
||||
name = map.get(uuid).value;
|
||||
} catch (final NullPointerException e) {
|
||||
name = null;
|
||||
}
|
||||
if (name != null) {
|
||||
final OfflinePlayer op = Bukkit.getOfflinePlayer(name);
|
||||
if (op.hasPlayedBefore()) {
|
||||
return new BukkitOfflinePlayer(op);
|
||||
}
|
||||
}
|
||||
for (final OfflinePlayer player : Bukkit.getOfflinePlayers()) {
|
||||
if (getUUID(player).equals(uuid)) {
|
||||
return new BukkitOfflinePlayer(player);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Player[] getOnlinePlayers() {
|
||||
if (getOnline == null) {
|
||||
Collection<? extends Player> onlinePlayers = Bukkit.getOnlinePlayers();
|
||||
return onlinePlayers.toArray(new Player[onlinePlayers.size()]);
|
||||
}
|
||||
try {
|
||||
final Object players = getOnline.invoke(Bukkit.getServer(), arg);
|
||||
if (players instanceof Player[]) {
|
||||
return (Player[]) players;
|
||||
} else {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Collection<? extends Player> p = (Collection<? extends Player>) players;
|
||||
return p.toArray(new Player[p.size()]);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
PS.debug("Failed to resolve online players");
|
||||
getOnline = null;
|
||||
Collection<? extends Player> onlinePlayers = Bukkit.getOnlinePlayers();
|
||||
return onlinePlayers.toArray(new Player[onlinePlayers.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(final String name) {
|
||||
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflinePlotPlayer[] getOfflinePlayers() {
|
||||
final OfflinePlayer[] ops = Bukkit.getOfflinePlayers();
|
||||
final BukkitOfflinePlayer[] toReturn = new BukkitOfflinePlayer[ops.length];
|
||||
for (int i = 0; i < ops.length; i++) {
|
||||
toReturn[i] = new BukkitOfflinePlayer(ops[i]);
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfflinePlotPlayer getOfflinePlayer(String name) {
|
||||
return new BukkitOfflinePlayer(Bukkit.getOfflinePlayer(name));
|
||||
}
|
||||
}
|
@ -0,0 +1,295 @@
|
||||
package com.plotsquared.bukkit.uuid;
|
||||
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.config.C;
|
||||
import com.intellectualcrafters.plot.config.Settings;
|
||||
import com.intellectualcrafters.plot.database.DBFunc;
|
||||
import com.intellectualcrafters.plot.database.SQLite;
|
||||
import com.intellectualcrafters.plot.object.RunnableVal;
|
||||
import com.intellectualcrafters.plot.object.StringWrapper;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandler;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandlerImplementation;
|
||||
import com.intellectualcrafters.plot.uuid.UUIDWrapper;
|
||||
|
||||
public class SQLUUIDHandler extends UUIDHandlerImplementation {
|
||||
|
||||
final String PROFILE_URL = "https://sessionserver.mojang.com/session/minecraft/profile/";
|
||||
final int MAX_REQUESTS = 500;
|
||||
final int INTERVAL = 12000;
|
||||
final JSONParser jsonParser = new JSONParser();
|
||||
private final SQLite _sqLite;
|
||||
|
||||
public SQLUUIDHandler(final UUIDWrapper wrapper) {
|
||||
super(wrapper);
|
||||
_sqLite = new SQLite("./plugins/PlotSquared/usercache.db");
|
||||
try {
|
||||
_sqLite.openConnection();
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
final PreparedStatement stmt = getConnection().prepareStatement(
|
||||
"CREATE TABLE IF NOT EXISTS `usercache` (uuid VARCHAR(32) NOT NULL, username VARCHAR(32) NOT NULL, PRIMARY KEY (uuid, username))");
|
||||
stmt.execute();
|
||||
stmt.close();
|
||||
} catch (final SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
startCaching(null);
|
||||
}
|
||||
|
||||
private Connection getConnection() {
|
||||
synchronized (_sqLite) {
|
||||
return _sqLite.getConnection();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startCaching(final Runnable whenDone) {
|
||||
if (!super.startCaching(whenDone)) {
|
||||
return false;
|
||||
}
|
||||
TaskManager.runTaskAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final HashBiMap<StringWrapper, UUID> toAdd = HashBiMap.create(new HashMap<StringWrapper, UUID>());
|
||||
final PreparedStatement statement = getConnection().prepareStatement("SELECT `uuid`, `username` FROM `usercache`");
|
||||
final ResultSet resultSet = statement.executeQuery();
|
||||
StringWrapper username;
|
||||
UUID uuid;
|
||||
while (resultSet.next()) {
|
||||
username = new StringWrapper(resultSet.getString("username"));
|
||||
uuid = UUID.fromString(resultSet.getString("uuid"));
|
||||
toAdd.put(new StringWrapper(username.value), uuid);
|
||||
}
|
||||
statement.close();
|
||||
add(toAdd);
|
||||
add(new StringWrapper("*"), DBFunc.everyone);
|
||||
|
||||
// This should be called as long as there are some unknown plots
|
||||
final ArrayDeque<UUID> toFetch = new ArrayDeque<>();
|
||||
for (final UUID u : UUIDHandler.getAllUUIDS()) {
|
||||
if (!uuidExists(u)) {
|
||||
toFetch.add(u);
|
||||
}
|
||||
}
|
||||
if (toFetch.isEmpty()) {
|
||||
if (whenDone != null) {
|
||||
whenDone.run();
|
||||
}
|
||||
return;
|
||||
}
|
||||
final FileUUIDHandler fileHandler = new FileUUIDHandler(SQLUUIDHandler.this.uuidWrapper);
|
||||
fileHandler.startCaching(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// If the file based UUID handler didn't cache it, then we can't cache offline mode
|
||||
// Also, trying to cache based on files again, is useless as that's what the file based uuid cacher does
|
||||
if (Settings.OFFLINE_MODE) {
|
||||
if (whenDone != null) {
|
||||
whenDone.run();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
TaskManager.runTaskAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (toFetch.isEmpty()) {
|
||||
if (whenDone != null) {
|
||||
whenDone.run();
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < Math.min(500, toFetch.size()); i++) {
|
||||
UUID uuid = toFetch.pop();
|
||||
HttpURLConnection connection = (HttpURLConnection) new URL(PROFILE_URL + uuid.toString().replace("-", "")).openConnection();
|
||||
InputStreamReader reader = new InputStreamReader(connection.getInputStream());
|
||||
JSONObject response = (JSONObject) jsonParser.parse(reader);
|
||||
String name = (String) response.get("name");
|
||||
if (name != null) {
|
||||
add(new StringWrapper(name), uuid);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
TaskManager.runTaskLaterAsync(this, INTERVAL);
|
||||
}
|
||||
});
|
||||
/*
|
||||
* This API is no longer accessible.
|
||||
*/
|
||||
// if (!Settings.OFFLINE_MODE) {
|
||||
// PS.debug(C.PREFIX.s() + "&cWill fetch &6" + toFetch.size() + "&c from mojang!");
|
||||
//
|
||||
// int i = 0;
|
||||
// final Iterator<UUID> iterator = toFetch.iterator();
|
||||
// while (iterator.hasNext()) {
|
||||
// final StringBuilder url = new StringBuilder("http://api.intellectualsites.com/uuid/?user=");
|
||||
// final List<UUID> currentIteration = new ArrayList<>();
|
||||
// while ((i++ <= 15) && iterator.hasNext()) {
|
||||
// final UUID _uuid = iterator.next();
|
||||
// url.append(_uuid.toString());
|
||||
// if (iterator.hasNext()) {
|
||||
// url.append(",");
|
||||
// }
|
||||
// currentIteration.add(_uuid);
|
||||
// }
|
||||
// PS.debug(C.PREFIX.s() + "&cWill attempt to fetch &6" + currentIteration.size() + "&c uuids from: &6" + url.toString());
|
||||
// try {
|
||||
// final HttpURLConnection connection = (HttpURLConnection) new URL(url.toString()).openConnection();
|
||||
// connection.setRequestProperty("User-Agent", "Mozilla/5.0");
|
||||
// final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
// String line;
|
||||
// final StringBuilder rawJSON = new StringBuilder();
|
||||
// while ((line = reader.readLine()) != null) {
|
||||
// rawJSON.append(line);
|
||||
// }
|
||||
// reader.close();
|
||||
// final JSONObject object = new JSONObject(rawJSON.toString());
|
||||
// for (final UUID _u : currentIteration) {
|
||||
// final Object o = object.getJSONObject(_u.toString().replace("-", "")).get("username");
|
||||
// if ((o == null) || !(o instanceof String)) {
|
||||
// continue;
|
||||
// }
|
||||
// add(new StringWrapper(o.toString()), _u);
|
||||
// }
|
||||
// } catch (final Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// i = 0;
|
||||
// }
|
||||
// }
|
||||
// if (whenDone != null) {
|
||||
// whenDone.run();
|
||||
// }
|
||||
}
|
||||
});
|
||||
} catch (final SQLException e) {
|
||||
throw new SQLUUIDHandlerException("Couldn't select :s", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetchUUID(final String name, final RunnableVal<UUID> ifFetch) {
|
||||
PS.debug(C.PREFIX.s() + "UUID for '" + name + "' was null. We'll cache this from the mojang servers!");
|
||||
if (ifFetch == null) {
|
||||
return;
|
||||
}
|
||||
TaskManager.runTaskAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
URL url = new URL(PROFILE_URL);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
connection.setUseCaches(false);
|
||||
connection.setDoInput(true);
|
||||
connection.setDoOutput(true);
|
||||
String body = JSONArray.toJSONString(Collections.singletonList(name));
|
||||
OutputStream stream = connection.getOutputStream();
|
||||
stream.write(body.getBytes());
|
||||
stream.flush();
|
||||
stream.close();
|
||||
JSONArray array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream()));
|
||||
JSONObject jsonProfile = (JSONObject) array.get(0);
|
||||
String id = (String) jsonProfile.get("id");
|
||||
String name = (String) jsonProfile.get("name");
|
||||
ifFetch.value = UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" + id.substring(20, 32));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
TaskManager.runTask(ifFetch);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleShutdown() {
|
||||
super.handleShutdown();
|
||||
try {
|
||||
getConnection().close();
|
||||
} catch (final SQLException e) {
|
||||
throw new SQLUUIDHandlerException("Couldn't close database connection", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(final StringWrapper name, final UUID uuid) {
|
||||
// Ignoring duplicates
|
||||
if (super.add(name, uuid)) {
|
||||
TaskManager.runTaskAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final PreparedStatement statement = getConnection().prepareStatement("REPLACE INTO usercache (`uuid`, `username`) VALUES(?, ?)");
|
||||
statement.setString(1, uuid.toString());
|
||||
statement.setString(2, name.toString());
|
||||
statement.execute();
|
||||
PS.debug(C.PREFIX.s() + "&cAdded '&6" + uuid + "&c' - '&6" + name + "&c'");
|
||||
} catch (final SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is useful for name changes
|
||||
*/
|
||||
@Override
|
||||
public void rename(final UUID uuid, final StringWrapper name) {
|
||||
super.rename(uuid, name);
|
||||
TaskManager.runTaskAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final PreparedStatement statement = getConnection().prepareStatement("UPDATE usercache SET `username`=? WHERE `uuid`=?");
|
||||
statement.setString(1, name.value);
|
||||
statement.setString(2, uuid.toString());
|
||||
statement.execute();
|
||||
PS.debug(C.PREFIX.s() + "Name change for '" + uuid + "' to '" + name.value + "'");
|
||||
} catch (final SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class SQLUUIDHandlerException extends RuntimeException {
|
||||
|
||||
SQLUUIDHandlerException(final String s, final Throwable c) {
|
||||
super("SQLUUIDHandler caused an exception: " + s, c);
|
||||
}
|
||||
}
|
||||
}
|
152
Bukkit/src/main/resources/plugin.yml
Normal file
152
Bukkit/src/main/resources/plugin.yml
Normal file
@ -0,0 +1,152 @@
|
||||
name: $name
|
||||
main: com.plotsquared.bukkit.BukkitMain
|
||||
version: $version
|
||||
load: STARTUP
|
||||
description: >
|
||||
Easy, yet powerful Plot World generation and management.
|
||||
authors: [Citymonstret, Empire92]
|
||||
softdepend: [WorldEdit, BarAPI, CameraAPI, Vault]
|
||||
loadbefore: [MultiWorld, Multiverse-Core]
|
||||
database: false
|
||||
commands:
|
||||
plots:
|
||||
description: PlotSquared PlotSquared command.
|
||||
aliases: [p,plot,ps,plotsquared,p2,2]
|
||||
permission: plots.use
|
||||
permission-message: "You are lacking the permission node 'plots.use'"
|
||||
permissions:
|
||||
plots.use:
|
||||
default: true
|
||||
plots.permpack.basicflags:
|
||||
default: op
|
||||
children:
|
||||
plots.set.flag: true
|
||||
plots.flag: true
|
||||
plots.flag.add: true
|
||||
plots.flag.remove: true
|
||||
plots.flag.list: true
|
||||
plots.flag.info: true
|
||||
plots.set.flag.titles.*: true
|
||||
plots.set.flag.greeting.*: true
|
||||
plots.set.flag.farewell.*: true
|
||||
plots.set.flag.notify-enter.*: true
|
||||
plots.set.flag.notify-leave.*: true
|
||||
plots.set.flag.feed.*: true
|
||||
plots.set.flag.heal.*: true
|
||||
plots.set.flag.invincible.*: true
|
||||
plots.set.flag.instabreak.*: true
|
||||
plots.set.flag.fly.*: true
|
||||
plots.set.flag.gamemode: true
|
||||
plots.set.flag.gamemode.creative: true
|
||||
plots.set.flag.gamemode.survival: true
|
||||
plots.set.flag.gamemode.adventure: true
|
||||
plots.set.flag.time.*: true
|
||||
plots.set.flag.weather.*: true
|
||||
plots.set.flag.music.*: true
|
||||
plots.set.flag.disable-physics.*: true
|
||||
plots.set.flag.pve.*: true
|
||||
plots.set.flag.pvp.*: true
|
||||
plots.set.flag.explosion.*: true
|
||||
plots.set.flag.hostile-interact.*: true
|
||||
plots.set.flag.hostile-attack.*: true
|
||||
plots.set.flag.player-interact.*: true
|
||||
plots.set.flag.animal-interact.*: true
|
||||
plots.set.flag.animal-attack.*: true
|
||||
plots.set.flag.tamed-interact.*: true
|
||||
plots.set.flag.tamed-attack.*: true
|
||||
plots.set.flag.misc-interact.*: true
|
||||
plots.set.flag.hanging-place.*: true
|
||||
plots.set.flag.hanging-break.*: true
|
||||
plots.set.flag.vehicle-use.*: true
|
||||
plots.set.flag.vehicle-place.*: true
|
||||
plots.set.flag.vehicle-break.*: true
|
||||
plots.set.flag.player-interact.*: true
|
||||
plots.set.flag.place.*: true
|
||||
plots.set.flag.break.*: true
|
||||
plots.set.flag.use.*: true
|
||||
plots.set.flag.forcefield.*: true
|
||||
plots.set.flag.price.*: true
|
||||
plots.set.flag.no-worldedit.*: true
|
||||
plots.permpack.basicinbox:
|
||||
default: op
|
||||
children:
|
||||
comments.notifications.enabled : true
|
||||
plots.inbox.read.public: true
|
||||
plots.inbox.modify.public: true
|
||||
plots.inbox.modify.public: true
|
||||
plots.inbox.write.public: true
|
||||
plots.inbox.read.public: true
|
||||
plots.inbox.read.report: true
|
||||
plots.inbox.write.report: true
|
||||
plots.inbox.read.report: true
|
||||
plots.inbox.read.owner: true
|
||||
plots.inbox.modify.owner: true
|
||||
plots.inbox.write.owner: true
|
||||
plots.inbox.read.owner: true
|
||||
plots.comment: true
|
||||
plots.inbox: true
|
||||
plots.permpack.wilderness:
|
||||
default: op
|
||||
children:
|
||||
plots.admin.interact.unowned: true
|
||||
plots.admin.destroy.unowned: true
|
||||
plots.admin.build.unowned: true
|
||||
plots.projectile.unowned: true
|
||||
plots.admin.vehicle.break.unowned: true
|
||||
plots.admin.pve.unowned: true
|
||||
plots.permpack.basic:
|
||||
default: op
|
||||
children:
|
||||
plots.use: true
|
||||
plots.info: true
|
||||
plots.claim: true
|
||||
plots.auto: true
|
||||
plots.home: true
|
||||
plots.clear: true
|
||||
plots.delete: true
|
||||
plots.list: true
|
||||
plots.list.mine: true
|
||||
plots.list.shared: true
|
||||
plots.list.world: true
|
||||
plots.list.all: true
|
||||
plots.list.forsale: true
|
||||
plots.list.unowned: true
|
||||
plots.list.unknown: true
|
||||
plots.set: true
|
||||
plots.visit: true
|
||||
plots.visit.owned: true
|
||||
plots.visit.shared: true
|
||||
plots.set.flag: true
|
||||
plots.flag.add: true
|
||||
plots.flag.remove: true
|
||||
plots.flag.list: true
|
||||
plots.flag.info: true
|
||||
plots.flag: true
|
||||
plots.buy: true
|
||||
plots.chat: true
|
||||
plots.confirm: true
|
||||
plots.toggle: true
|
||||
plots.toggle.titles: true
|
||||
plots.toggle.chat: true
|
||||
plots.set.biome: true
|
||||
plots.set.home: true
|
||||
plots.merge: true
|
||||
plots.merge.other: true
|
||||
plots.merge.4: true
|
||||
plots.unlink: true
|
||||
plots.denied: true
|
||||
plots.add: true
|
||||
plots.trust: true
|
||||
plots.deny: true
|
||||
plots.remove: true
|
||||
plots.untrust: true
|
||||
plots.undeny: true
|
||||
plots.kick: true
|
||||
plots.download: true
|
||||
plots.save: true
|
||||
plots.done: true
|
||||
plots.continue: true
|
||||
plots.worldedit.bypass:
|
||||
default: false
|
||||
plots.gamemode.bypass:
|
||||
default: op
|
Reference in New Issue
Block a user