diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index 3a6d64f38..94ea558a0 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -361,7 +361,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain if (!PS.get().setupPlotWorld(world, id, result)) { return null; } - return (ChunkGenerator) result.specify(); + return (ChunkGenerator) result.specify(world); } @Override @@ -665,7 +665,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain } @Override - public GeneratorWrapper wrapPlotGenerator(IndependentPlotGenerator generator) { + public GeneratorWrapper wrapPlotGenerator(String world, IndependentPlotGenerator generator) { return new BukkitPlotGenerator(generator); } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/block/GenChunk.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/block/GenChunk.java index 21c03f6d1..90d235fc4 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/block/GenChunk.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/block/GenChunk.java @@ -168,8 +168,6 @@ public class GenChunk extends ScopedLocalBlockQueue { return new Location(getWorld(), getX() << 4, 0, getZ() << 4); } - - public GenChunk clone() { GenChunk toReturn = new GenChunk(chunk, new ChunkWrapper(getWorld(), chunk.getX(), chunk.getZ())); if (this.result != null) { diff --git a/Core/src/main/java/com/intellectualcrafters/plot/IPlotMain.java b/Core/src/main/java/com/intellectualcrafters/plot/IPlotMain.java index 6c644b38b..bb5948d41 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/IPlotMain.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/IPlotMain.java @@ -222,7 +222,7 @@ public interface IPlotMain extends ILogger { */ GeneratorWrapper getGenerator(String world, String name); - GeneratorWrapper wrapPlotGenerator(IndependentPlotGenerator generator); + GeneratorWrapper wrapPlotGenerator(String world, IndependentPlotGenerator generator); /** * Register the chunk processor which will clean out chunks that have too diff --git a/Core/src/main/java/com/intellectualcrafters/plot/commands/Leave.java b/Core/src/main/java/com/intellectualcrafters/plot/commands/Leave.java new file mode 100644 index 000000000..abc3d26ba --- /dev/null +++ b/Core/src/main/java/com/intellectualcrafters/plot/commands/Leave.java @@ -0,0 +1,35 @@ +package com.intellectualcrafters.plot.commands; + +import com.intellectualcrafters.plot.config.C; +import com.intellectualcrafters.plot.object.Plot; +import com.intellectualcrafters.plot.object.PlotPlayer; +import com.intellectualcrafters.plot.object.RunnableVal2; +import com.intellectualcrafters.plot.object.RunnableVal3; +import com.plotsquared.general.commands.Command; +import com.plotsquared.general.commands.CommandDeclaration; +import java.util.*; +import java.util.Set; + +@CommandDeclaration(command = "leave", + description = "Leave a plot", + permission = "plots.leave", + category = CommandCategory.CLAIMING, + requiredType = RequiredType.NONE) +public class Leave extends Command { + public Leave(Command parent, boolean isStatic) { + super(MainCommand.getInstance(), true); + } + + @Override + public void execute(PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) throws CommandException { + final Plot plot = check(player.getCurrentPlot(), C.NOT_IN_PLOT); + checkTrue(plot.hasOwner(), C.PLOT_UNOWNED); + checkTrue(plot.isAdded(player.getUUID()), C.NO_PLOT_PERMS); + checkTrue(args.length == 0, C.COMMAND_SYNTAX, getUsage()); + if (plot.isOwner(player.getUUID())) { + Set owners = plot.getOwners(); + } else { + + } + } +} diff --git a/Core/src/main/java/com/intellectualcrafters/plot/generator/ClassicPlotManager.java b/Core/src/main/java/com/intellectualcrafters/plot/generator/ClassicPlotManager.java index f558bab1a..ace2a8a90 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/generator/ClassicPlotManager.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/generator/ClassicPlotManager.java @@ -81,7 +81,7 @@ public class ClassicPlotManager extends SquarePlotManager { LocalBlockQueue queue = plotArea.getQueue(false); for (RegionWrapper region : plot.getRegions()) { Location pos1 = new Location(plotArea.worldname, region.minX, 1, region.minZ); - Location pos2 = new Location(plotArea.worldname, region.maxX, 255, region.maxZ); + Location pos2 = new Location(plotArea.worldname, region.maxX, Math.min(plotArea.MAX_BUILD_HEIGHT, 255), region.maxZ); queue.setCuboid(pos1, pos2, blocks); } queue.enqueue(); @@ -97,7 +97,7 @@ public class ClassicPlotManager extends SquarePlotManager { LocalBlockQueue queue = plotArea.getQueue(false); for (RegionWrapper region : plot.getRegions()) { Location pos1 = new Location(plotArea.worldname, region.minX, dpw.PLOT_HEIGHT + 1, region.minZ); - Location pos2 = new Location(plotArea.worldname, region.maxX, 255, region.maxZ); + Location pos2 = new Location(plotArea.worldname, region.maxX, Math.min(plotArea.MAX_BUILD_HEIGHT, 255), region.maxZ); queue.setCuboid(pos1, pos2, blocks); } queue.enqueue(); @@ -147,7 +147,7 @@ public class ClassicPlotManager extends SquarePlotManager { if (!plot.getMerged(0)) { int z = bottom.getZ(); for (int x = bottom.getX(); x <= top.getX(); x++) { - for (int y = dpw.PLOT_HEIGHT; y <= 255; y++) { + for (int y = dpw.PLOT_HEIGHT; y <= Math.min(plotArea.MAX_BUILD_HEIGHT, 255); y++) { queue.setBlock(x, y, z, blocks[random.random(blocks.length)]); } } @@ -155,7 +155,7 @@ public class ClassicPlotManager extends SquarePlotManager { if (!plot.getMerged(3)) { int x = bottom.getX(); for (int z = bottom.getZ(); z <= top.getZ(); z++) { - for (int y = dpw.PLOT_HEIGHT; y <= 255; y++) { + for (int y = dpw.PLOT_HEIGHT; y <= Math.min(plotArea.MAX_BUILD_HEIGHT, 255); y++) { queue.setBlock(x, y, z, blocks[random.random(blocks.length)]); } } @@ -164,7 +164,7 @@ public class ClassicPlotManager extends SquarePlotManager { if (!plot.getMerged(2)) { int z = top.getZ(); for (int x = bottom.getX(); x <= top.getX(); x++) { - for (int y = dpw.PLOT_HEIGHT; y <= 255; y++) { + for (int y = dpw.PLOT_HEIGHT; y <= Math.min(plotArea.MAX_BUILD_HEIGHT, 255); y++) { queue.setBlock(x, y, z, blocks[random.random(blocks.length)]); } } @@ -172,15 +172,15 @@ public class ClassicPlotManager extends SquarePlotManager { if (!plot.getMerged(1)) { int x = top.getX(); for (int z = bottom.getZ(); z <= top.getZ(); z++) { - for (int y = dpw.PLOT_HEIGHT; y <= 255; y++) { + for (int y = dpw.PLOT_HEIGHT; y <= Math.min(plotArea.MAX_BUILD_HEIGHT, 255); y++) { queue.setBlock(x, y, z, blocks[random.random(blocks.length)]); } } } if (plot.isBasePlot()) { for (RegionWrapper region : plot.getRegions()) { - Location pos1 = new Location(plotArea.worldname, region.minX, 255, region.minZ); - Location pos2 = new Location(plotArea.worldname, region.maxX, 255, region.maxZ); + Location pos1 = new Location(plotArea.worldname, region.minX, Math.min(plotArea.MAX_BUILD_HEIGHT, 255), region.minZ); + Location pos2 = new Location(plotArea.worldname, region.maxX, Math.min(plotArea.MAX_BUILD_HEIGHT, 255), region.maxZ); queue.setCuboid(pos1, pos2, blocks); } } @@ -288,7 +288,7 @@ public class ClassicPlotManager extends SquarePlotManager { LocalBlockQueue queue = plotArea.getQueue(false); queue.setCuboid( new Location(plotArea.worldname, sx, Math.min(dpw.WALL_HEIGHT, dpw.ROAD_HEIGHT) + 1, sz + 1), - new Location(plotArea.worldname, ex, 255, ez - 1), PlotBlock.get((short) 0, (byte) 0)); + new Location(plotArea.worldname, ex, Math.min(plotArea.MAX_BUILD_HEIGHT, 255), ez - 1), PlotBlock.get((short) 0, (byte) 0)); queue.setCuboid(new Location(plotArea.worldname, sx, 0, sz + 1), new Location(plotArea.worldname, ex, 0, ez - 1), PlotBlock.get((short) 7, (byte) 0)); @@ -320,7 +320,7 @@ public class ClassicPlotManager extends SquarePlotManager { LocalBlockQueue queue = plotArea.getQueue(false); queue.setCuboid( new Location(plotArea.worldname, sx + 1, Math.min(dpw.WALL_HEIGHT, dpw.ROAD_HEIGHT) + 1, sz), - new Location(plotArea.worldname, ex - 1, 255, ez), PlotBlock.get((short) 0, (byte) 0)); + new Location(plotArea.worldname, ex - 1, Math.min(plotArea.MAX_BUILD_HEIGHT, 255), ez), PlotBlock.get((short) 0, (byte) 0)); queue.setCuboid(new Location(plotArea.worldname, sx + 1, 0, sz), new Location(plotArea.worldname, ex - 1, 0, ez), PlotBlock.get((short) 7, (byte) 0)); queue.setCuboid(new Location(plotArea.worldname, sx + 1, 1, sz), @@ -370,7 +370,7 @@ public class ClassicPlotManager extends SquarePlotManager { int ez = pos2.getZ() + 1; LocalBlockQueue queue = plotArea.getQueue(false); queue.setCuboid(new Location(plotArea.worldname, sx, Math.min(dpw.PLOT_HEIGHT, dpw.ROAD_HEIGHT) + 1, sz), - new Location(plotArea.worldname, ex, 255, ez), PlotBlock.get((short) 0, (byte) 0)); + new Location(plotArea.worldname, ex, Math.min(plotArea.MAX_BUILD_HEIGHT, 255), ez), PlotBlock.get((short) 0, (byte) 0)); queue.setCuboid(new Location(plotArea.worldname, sx, 1, sz + 1), new Location(plotArea.worldname, ex, dpw.PLOT_HEIGHT - 1, ez - 1), dpw.MAIN_BLOCK); queue.setCuboid(new Location(plotArea.worldname, sx, dpw.PLOT_HEIGHT, sz + 1), @@ -390,7 +390,7 @@ public class ClassicPlotManager extends SquarePlotManager { int ex = pos2.getX() + 1; LocalBlockQueue queue = plotArea.getQueue(false); queue.setCuboid(new Location(plotArea.worldname, sx, Math.min(dpw.PLOT_HEIGHT, dpw.ROAD_HEIGHT) + 1, sz), - new Location(plotArea.worldname, ex, 255, ez), PlotBlock.get((short) 0, (byte) 0)); + new Location(plotArea.worldname, ex, Math.min(plotArea.MAX_BUILD_HEIGHT, 255), ez), PlotBlock.get((short) 0, (byte) 0)); queue.setCuboid(new Location(plotArea.worldname, sx + 1, 1, sz), new Location(plotArea.worldname, ex - 1, dpw.PLOT_HEIGHT - 1, ez), dpw.MAIN_BLOCK); queue.setCuboid(new Location(plotArea.worldname, sx + 1, dpw.PLOT_HEIGHT, sz), diff --git a/Core/src/main/java/com/intellectualcrafters/plot/generator/HybridGen.java b/Core/src/main/java/com/intellectualcrafters/plot/generator/HybridGen.java index 3b2ac579f..ffa6801b9 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/generator/HybridGen.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/generator/HybridGen.java @@ -26,11 +26,7 @@ public class HybridGen extends IndependentPlotGenerator { public void generateChunk(ScopedLocalBlockQueue result, PlotArea settings, PseudoRandom random) { HybridPlotWorld hpw = (HybridPlotWorld) settings; // Biome - for (short x = 0; x < 16; x++) { - for (short z = 0; z < 16; z++) { - result.fillBiome(hpw.PLOT_BIOME); - } - } + result.fillBiome(hpw.PLOT_BIOME); // Bedrock if (hpw.PLOT_BEDROCK) { for (short x = 0; x < 16; x++) { diff --git a/Core/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotManager.java b/Core/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotManager.java index f6dd0deec..b17b0e9cc 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotManager.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/generator/HybridPlotManager.java @@ -61,7 +61,7 @@ public class HybridPlotManager extends ClassicPlotManager { Location bot = getPlotBottomLocAbs(hpw, id2); Location top = getPlotTopLocAbs(hpw, id); Location pos1 = new Location(plotArea.worldname, top.getX() + 1, 0, bot.getZ() - 1); - Location pos2 = new Location(plotArea.worldname, bot.getX(), 255, top.getZ() + 1); + Location pos2 = new Location(plotArea.worldname, bot.getX(), Math.min(plotArea.MAX_BUILD_HEIGHT, 255), top.getZ() + 1); MainUtil.resetBiome(plotArea, pos1, pos2); if (!hpw.ROAD_SCHEMATIC_ENABLED) { return true; @@ -108,7 +108,7 @@ public class HybridPlotManager extends ClassicPlotManager { Location bot = getPlotBottomLocAbs(hpw, id2); Location top = getPlotTopLocAbs(hpw, id); Location pos1 = new Location(plotArea.worldname, bot.getX() - 1, 0, top.getZ() + 1); - Location pos2 = new Location(plotArea.worldname, top.getX() + 1, 255, bot.getZ()); + Location pos2 = new Location(plotArea.worldname, top.getX() + 1, Math.min(plotArea.MAX_BUILD_HEIGHT, 255), bot.getZ()); MainUtil.resetBiome(plotArea, pos1, pos2); if (!hpw.ROAD_SCHEMATIC_ENABLED) { return true; @@ -128,7 +128,7 @@ public class HybridPlotManager extends ClassicPlotManager { Location pos1 = getPlotTopLocAbs(hpw, id).add(1, 0, 1); Location pos2 = getPlotBottomLocAbs(hpw, id2); pos1.setY(0); - pos2.setY(256); + pos2.setY(Math.min(plotArea.MAX_BUILD_HEIGHT, 255)); LocalBlockQueue queue = hpw.getQueue(false); createSchemAbs(hpw, queue, pos1, pos2, true); if (hpw.ROAD_SCHEMATIC_ENABLED) { @@ -145,7 +145,7 @@ public class HybridPlotManager extends ClassicPlotManager { * to have 512x512 sized plots.

*/ @Override - public boolean clearPlot(PlotArea plotArea, Plot plot, final Runnable whenDone) { + public boolean clearPlot(final PlotArea plotArea, Plot plot, final Runnable whenDone) { final String world = plotArea.worldname; final HybridPlotWorld dpw = (HybridPlotWorld) plotArea; Location pos1 = plot.getBottomAbs(); @@ -189,7 +189,7 @@ public class HybridPlotManager extends ClassicPlotManager { top.setY(dpw.PLOT_HEIGHT + 1); queue.setCuboid(bot, top, plotfloor); bot.setY(dpw.PLOT_HEIGHT + 1); - top.setY(256); + top.setY(plotArea.MAX_BUILD_HEIGHT); queue.setCuboid(bot, top, air); // And finally set the schematic, the y value is unimportant for this function pastePlotSchematic(dpw, queue, bot, top); diff --git a/Core/src/main/java/com/intellectualcrafters/plot/generator/IndependentPlotGenerator.java b/Core/src/main/java/com/intellectualcrafters/plot/generator/IndependentPlotGenerator.java index 7cdbc7613..4602106a0 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/generator/IndependentPlotGenerator.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/generator/IndependentPlotGenerator.java @@ -70,8 +70,8 @@ public abstract class IndependentPlotGenerator { * @param * @return */ - public GeneratorWrapper specify() { - return (GeneratorWrapper) PS.get().IMP.wrapPlotGenerator(this); + public GeneratorWrapper specify(String world) { + return (GeneratorWrapper) PS.get().IMP.wrapPlotGenerator(world, this); } @Override diff --git a/Nukkit/build.gradle b/Nukkit/build.gradle new file mode 100644 index 000000000..52e56f3e4 --- /dev/null +++ b/Nukkit/build.gradle @@ -0,0 +1,51 @@ +repositories { + maven {url "https://hub.spigotmc.org/nexus/content/groups/public/"} + maven { url = "https://oss.sonatype.org/content/repositories/snapshots/"} + maven {url "http://nexus.hc.to/content/repositories/pub_releases"} +} + +dependencies { + compile project(':Core') + compile 'cn.nukkit:nukkit:1.0-SNAPSHOT' + compile 'com.google.guava:guava:17.0' +} + +configurations.all { + resolutionStrategy { + force 'com.google.guava:guava:17.0' + } +} + +sourceCompatibility = 1.7 +targetCompatibility = 1.7 + +processResources { + from('src/main/resources') { + include 'plugin.yml' + expand( + name: project.parent.name, + version: project.parent.version + ) + } +} +// We only want the shadow jar produced +jar.enabled = false + +shadowJar { + dependencies { + include(dependency(':Core')) + } + archiveName = "${parent.name}-${project.name}-${parent.version}.jar" + destinationDir = file '../target' + + relocate('com.google.gson', 'com.sk89q.worldedit.internal.gson') + relocate 'org.yaml.snakeyaml', 'com.boydti.fawe.yaml' + relocate 'com.google.common', 'com.sk89q.worldedit.internal.common' +} + +shadowJar.doLast { + task -> + ant.checksum file: task.archivePath +} + +build.dependsOn(shadowJar); diff --git a/Nukkit/build/resources/main/plugin.yml b/Nukkit/build/resources/main/plugin.yml new file mode 100644 index 000000000..0afd5358d --- /dev/null +++ b/Nukkit/build/resources/main/plugin.yml @@ -0,0 +1,6 @@ +name: "PlotSquared" +version: "3.4.6-SNAPSHOT-0557671" +author: Empire92 +api: ["1.0.0"] +main: com.plotsquared.nukkit.NukkitMain +load: STARTUP \ No newline at end of file diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/NukkitMain.java b/Nukkit/src/main/java/com/plotsquared/nukkit/NukkitMain.java new file mode 100644 index 000000000..c56cc5129 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/NukkitMain.java @@ -0,0 +1,410 @@ +package com.plotsquared.nukkit; + +import cn.nukkit.Nukkit; +import cn.nukkit.OfflinePlayer; +import cn.nukkit.Player; +import cn.nukkit.entity.Entity; +import cn.nukkit.event.Listener; +import cn.nukkit.level.Level; +import cn.nukkit.level.generator.Generator; +import cn.nukkit.metadata.MetadataValue; +import cn.nukkit.plugin.Plugin; +import cn.nukkit.plugin.PluginBase; +import com.intellectualcrafters.plot.IPlotMain; +import com.intellectualcrafters.plot.PS; +import com.intellectualcrafters.plot.config.C; +import com.intellectualcrafters.plot.config.Settings; +import com.intellectualcrafters.plot.generator.GeneratorWrapper; +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.chat.PlainChatManager; +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.SchematicHandler; +import com.intellectualcrafters.plot.util.SetupUtils; +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.util.block.QueueProvider; +import com.plotsquared.nukkit.generator.NukkitPlotGenerator; +import com.plotsquared.nukkit.listeners.PlayerEvents; +import com.plotsquared.nukkit.listeners.WorldEvents; +import com.plotsquared.nukkit.util.Metrics; +import com.plotsquared.nukkit.util.NukkitChunkManager; +import com.plotsquared.nukkit.util.NukkitCommand; +import com.plotsquared.nukkit.util.NukkitEventUtil; +import com.plotsquared.nukkit.util.NukkitHybridUtils; +import com.plotsquared.nukkit.util.NukkitInventoryUtil; +import com.plotsquared.nukkit.util.NukkitSchematicHandler; +import com.plotsquared.nukkit.util.NukkitSetupUtils; +import com.plotsquared.nukkit.util.NukkitTaskManager; +import com.plotsquared.nukkit.util.NukkitUtil; +import com.plotsquared.nukkit.util.block.NukkitHybridGen; +import com.plotsquared.nukkit.util.block.NukkitLocalQueue; +import com.plotsquared.nukkit.uuid.FileUUIDHandler; +import com.plotsquared.nukkit.uuid.LowerOfflineUUIDWrapper; +import com.sk89q.worldedit.WorldEdit; +import java.io.File; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public final class NukkitMain extends PluginBase implements Listener, IPlotMain { + + public static WorldEdit worldEdit; + + private int[] version; + + @Override + public int[] getServerVersion() { + if (this.version == null) { + try { + this.version = new int[3]; + String[] split = Nukkit.API_VERSION.split("\\."); + this.version[0] = Integer.parseInt(split[0]); + this.version[1] = Integer.parseInt(split[1]); + if (split.length == 3) { + this.version[2] = Integer.parseInt(split[2]); + } + } catch (NumberFormatException e) { + return new int[]{1, 0, 0}; + } + } + return this.version; + } + + @Override + public void onEnable() { + try { + getServer().getName(); + new PS(this, "Nukkit"); + if (Settings.Enabled_Components.METRICS) { + new Metrics(this).start(); + PS.log(C.PREFIX + "&6Metrics enabled."); + } else { + PS.log(C.CONSOLE_PLEASE_ENABLE_METRICS); + } + Generator.addGenerator(NukkitHybridGen.class, "PlotSquared", 1); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + @Override + public void onDisable() { + PS.get().disable(); + getServer().getScheduler().cancelAllTasks(); + } + + @Override + public void log(String message) { + try { + message = C.color(message); + if (!Settings.Chat.CONSOLE_COLOR) { + message = message.replaceAll('\u00A7' + "[0-9]", ""); + } + this.getServer().getConsoleSender().sendMessage(message); + } catch (Throwable ignored) { + System.out.println(ConsoleColors.fromString(message)); + } + } + + @Override + public void disable() { + onDisable(); + } + + @Override + public int[] getPluginVersion() { + String ver = getDescription().getVersion(); + if (ver.contains("-")) { + ver = ver.split("-")[0]; + } + String[] split = ver.split("\\."); + return new int[]{Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2])}; + } + + @Override public String getPluginVersionString() { + return getDescription().getVersion(); + } + + @Override + public void registerCommands() { + NukkitCommand bukkitCommand = new NukkitCommand("plot", new String[] {"p","plot","ps","plotsquared","p2","2"}); + getServer().getCommandMap().register("plot", bukkitCommand); + } + + @Override + public File getDirectory() { + return getDataFolder(); + } + + @Override + public File getWorldContainer() { + return new File("worlds"); + } + + @Override + public TaskManager getTaskManager() { + return new NukkitTaskManager(this); + } + + @Override + public void runEntityTask() { + PS.log(C.PREFIX + "KillAllEntities started."); + TaskManager.runTaskRepeat(new Runnable() { + @Override + public void run() { + PS.get().foreachPlotArea(new RunnableVal() { + @Override + public void run(PlotArea plotArea) { + Level world = getServer().getLevelByName(plotArea.worldname); + try { + if (world == null) { + return; + } + Entity[] entities = world.getEntities(); + for (Entity entity : entities) { + if (entity instanceof Player) { + continue; + } + com.intellectualcrafters.plot.object.Location location = NukkitUtil.getLocation(entity.getLocation()); + Plot plot = location.getPlot(); + if (plot == null) { + if (location.isPlotArea()) { + entity.kill(); + } + continue; + } + List meta = entity.getMetadata("plot"); + if (meta.isEmpty()) { + continue; + } + Plot origin = (Plot) meta.get(0).value(); + if (!plot.equals(origin.getBasePlot(false))) { + entity.kill(); + } + continue; + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + }); + } + }, 20); + } + + @Override + public void registerPlayerEvents() { + getServer().getPluginManager().registerEvents(new PlayerEvents(), this); + } + + @Override + public void registerInventoryEvents() { + PS.debug("Not implemented: registerPlotPlusEvents"); + } + + @Override + public void registerPlotPlusEvents() { + PS.debug("Not implemented: registerPlotPlusEvents"); + } + + @Override + public void registerForceFieldEvents() { + PS.debug("Not implemented: registerPlotPlusEvents"); + } + + @Override + public boolean initWorldEdit() { + if (getServer().getPluginManager().getPlugin("WorldEdit") != null) { + worldEdit = WorldEdit.getInstance(); + return true; + } + return false; + } + + @Override + public EconHandler getEconomyHandler() { + return null; + } + + @Override + public QueueProvider initBlockQueue() { + return QueueProvider.of(NukkitLocalQueue.class, null); + } + + @Override + public WorldUtil initWorldUtil() { + return new NukkitUtil(this); + } + + @Override + public boolean initPlotMeConverter() { + return false; // No PlotMe for MCPE + } + + @Override + public GeneratorWrapper getGenerator(String world, String name) { + if (name == null) { + return null; + } + HashMap map = new HashMap(); + map.put("world", world); + try { + Class gen = Generator.getGenerator(name); + if (gen != null) { + Generator instance = gen.getConstructor(Map.class).newInstance(map); + if (GeneratorWrapper.class.isAssignableFrom(gen.getClass())) { + return (GeneratorWrapper) instance; + } + map.put("generator", instance); + return new NukkitPlotGenerator(map); + } + } catch (Throwable e) { + e.printStackTrace(); + } + return new NukkitHybridGen(map); + } + + @Override + public HybridUtils initHybridUtils() { + return new NukkitHybridUtils(); + } + + @Override + public SetupUtils initSetupUtils() { + return new NukkitSetupUtils(this); + } + + @Override + public UUIDHandlerImplementation initUUIDHandler() { + Settings.UUID.FORCE_LOWERCASE = true; + Settings.UUID.OFFLINE = true; + LowerOfflineUUIDWrapper wrapper = new LowerOfflineUUIDWrapper(); + return new FileUUIDHandler(wrapper); + } + + @Override + public ChunkManager initChunkManager() { + return new NukkitChunkManager(); + } + + @Override + public EventUtil initEventUtil() { + return new NukkitEventUtil(this); + } + + @Override + public void unregister(PlotPlayer player) { + NukkitUtil.removePlayer(player.getName()); + } + + @Override + public void registerChunkProcessor() { + PS.debug("Not implemented: registerChunkProcessor"); + } + + @Override + public void registerWorldEvents() { + getServer().getPluginManager().registerEvents(new WorldEvents(), this); + } + + @Override + public InventoryUtil initInventoryUtil() { + return new NukkitInventoryUtil(); + } + + @Override + public void startMetrics() { + new Metrics(this).start(); + PS.log(C.PREFIX + "&6Metrics enabled."); + } + + @Override + public void setGenerator(String worldName) { + throw new UnsupportedOperationException("Not implemented: setGenerator"); + } + + private void setGenerator(Level level, Generator generator) { + try { + Field fieldClass = Level.class.getDeclaredField("generator"); + Field fieldInstance = Level.class.getDeclaredField("generatorInstance"); + fieldClass.setAccessible(true); + fieldInstance.setAccessible(true); + fieldClass.set(level, generator.getClass()); + fieldInstance.set(level, generator); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + @Override + public SchematicHandler initSchematicHandler() { + return new NukkitSchematicHandler(this); + } + + @Override + public AbstractTitle initTitleManager() { + // Already initialized in UUID handler + return AbstractTitle.TITLE_CLASS; + } + + @Override + public PlotPlayer wrapPlayer(Object player) { + if (player instanceof Player) { + return NukkitUtil.getPlayer((Player) player); + } + if (player instanceof OfflinePlayer) { + return NukkitUtil.getPlayer((OfflinePlayer) player); + } + if (player instanceof String) { + return UUIDHandler.getPlayer((String) player); + } + if (player instanceof UUID) { + return UUIDHandler.getPlayer((UUID) player); + } + return null; + } + + @Override + public String getNMSPackage() { + return ""; + } + + @Override + public ChatManager initChatManager() { + return new PlainChatManager(); + } + + @Override + public GeneratorWrapper wrapPlotGenerator(String world, IndependentPlotGenerator generator) { + HashMap settings = new HashMap<>(); + settings.put("world", world); + settings.put("plot-generator", generator); + return new NukkitPlotGenerator(settings); + } + + @Override + public List getPluginIds() { + ArrayList names = new ArrayList<>(); + for (Map.Entry entry : getServer().getPluginManager().getPlugins().entrySet()) { + Plugin plugin = entry.getValue(); + names.add(entry.getKey() + ';' + plugin.getDescription().getVersion() + ':' + plugin.isEnabled()); + } + return names; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/ClusterFlagRemoveEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/ClusterFlagRemoveEvent.java new file mode 100644 index 000000000..42ed22303 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/ClusterFlagRemoveEvent.java @@ -0,0 +1,61 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.event.Cancellable; +import cn.nukkit.event.Event; +import cn.nukkit.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 final 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(Flag flag, PlotCluster cluster) { + this.cluster = cluster; + this.flag = flag; + } + + public static HandlerList getHandlers() { + return handlers; + } + + /** + * Get the cluster involved. + * + * @return PlotCluster + */ + public PlotCluster getCluster() { + return this.cluster; + } + + /** + * Get the flag involved. + * + * @return Flag + */ + public Flag getFlag() { + return this.flag; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(boolean b) { + this.cancelled = b; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerClaimPlotEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerClaimPlotEvent.java new file mode 100644 index 000000000..fccb184d1 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerClaimPlotEvent.java @@ -0,0 +1,57 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.Player; +import cn.nukkit.event.Cancellable; +import cn.nukkit.event.HandlerList; +import cn.nukkit.event.player.PlayerEvent; +import com.intellectualcrafters.plot.object.Plot; + +public class PlayerClaimPlotEvent extends PlayerEvent implements Cancellable { + + private static final 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(Player player, Plot plot, boolean auto) { + this.player = player; + this.plot = plot; + this.auto = auto; + } + + public static HandlerList getHandlers() { + return handlers; + } + + /** + * Get the plot involved + * + * @return Plot + */ + public Plot getPlot() { + return this.plot; + } + + /** + * @return true if it was an automated claim, else false + */ + public boolean wasAuto() { + return this.auto; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(boolean b) { + this.cancelled = b; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerEnterPlotEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerEnterPlotEvent.java new file mode 100644 index 000000000..8ac37ac9e --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerEnterPlotEvent.java @@ -0,0 +1,37 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.Player; +import cn.nukkit.event.HandlerList; +import cn.nukkit.event.player.PlayerEvent; +import com.intellectualcrafters.plot.object.Plot; + +public class PlayerEnterPlotEvent extends PlayerEvent { + + private static final HandlerList handlers = new HandlerList(); + private final Plot plot; + private final Player player; + + /** + * Called when a player leaves a plot. + * + * @param player Player that entered the plot + * @param plot Plot that was entered + */ + public PlayerEnterPlotEvent(Player player, Plot plot) { + this.player = player; + this.plot = plot; + } + + public static HandlerList getHandlers() { + return handlers; + } + + /** + * Get the plot involved. + * + * @return Plot + */ + public Plot getPlot() { + return this.plot; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerLeavePlotEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerLeavePlotEvent.java new file mode 100644 index 000000000..0937e7aea --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerLeavePlotEvent.java @@ -0,0 +1,41 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.Player; +import cn.nukkit.event.HandlerList; +import cn.nukkit.event.player.PlayerEvent; +import com.intellectualcrafters.plot.object.Plot; + +/** + + + */ +public class PlayerLeavePlotEvent extends PlayerEvent { + + private static final 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(Player player, Plot plot) { + this.player = player; + this.plot = plot; + } + + public static HandlerList getHandlers() { + return handlers; + } + + /** + * Get the plot involved + * + * @return Plot + */ + public Plot getPlot() { + return this.plot; + } + +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerPlotDeniedEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerPlotDeniedEvent.java new file mode 100644 index 000000000..f17e07c2b --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerPlotDeniedEvent.java @@ -0,0 +1,61 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.Player; +import cn.nukkit.event.HandlerList; +import com.intellectualcrafters.plot.object.Plot; +import java.util.UUID; + +public class PlayerPlotDeniedEvent extends PlotEvent { + + private static final 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(Player initiator, Plot plot, UUID player, boolean added) { + super(plot); + this.initiator = initiator; + this.added = added; + this.player = player; + } + + public static HandlerList getHandlers() { + return handlers; + } + + /** + * If a user was added. + * + * @return boolean + */ + public boolean wasAdded() { + return this.added; + } + + /** + * The player added/removed. + * + * @return UUID + */ + public UUID getPlayer() { + return this.player; + } + + /** + * The player initiating the action. + * + * @return Player + */ + public Player getInitiator() { + return this.initiator; + } + +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerPlotHelperEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerPlotHelperEvent.java new file mode 100644 index 000000000..ffc94e915 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerPlotHelperEvent.java @@ -0,0 +1,64 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.Player; +import cn.nukkit.event.HandlerList; +import com.intellectualcrafters.plot.object.Plot; +import java.util.UUID; + +/** + + + */ +public class PlayerPlotHelperEvent extends PlotEvent { + + private static final 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(Player initiator, Plot plot, UUID player, boolean added) { + super(plot); + this.initiator = initiator; + this.added = added; + this.player = player; + } + + public static HandlerList getHandlers() { + return handlers; + } + + /** + * If a player was added + * + * @return boolean + */ + public boolean wasAdded() { + return this.added; + } + + /** + * The UUID added/removed + * + * @return UUID + */ + public UUID getPlayer() { + return this.player; + } + + /** + * The player initiating the action + * + * @return Player + */ + public Player getInitiator() { + return this.initiator; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerPlotTrustedEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerPlotTrustedEvent.java new file mode 100644 index 000000000..bd1c20a6d --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerPlotTrustedEvent.java @@ -0,0 +1,64 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.Player; +import cn.nukkit.event.HandlerList; +import com.intellectualcrafters.plot.object.Plot; +import java.util.UUID; + +/** + + + */ +public class PlayerPlotTrustedEvent extends PlotEvent { + + private static final 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(Player initiator, Plot plot, UUID player, boolean added) { + super(plot); + this.initiator = initiator; + this.added = added; + this.player = player; + } + + public static HandlerList getHandlers() { + return handlers; + } + + /** + * If a player was added + * + * @return boolean + */ + public boolean wasAdded() { + return this.added; + } + + /** + * The UUID added/removed + * + * @return UUID + */ + public UUID getPlayer() { + return this.player; + } + + /** + * The player initiating the action + * + * @return Player + */ + public Player getInitiator() { + return this.initiator; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerTeleportToPlotEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerTeleportToPlotEvent.java new file mode 100644 index 000000000..089bb3ffb --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlayerTeleportToPlotEvent.java @@ -0,0 +1,63 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.Player; +import cn.nukkit.event.Cancellable; +import cn.nukkit.event.HandlerList; +import cn.nukkit.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(Player player, Location from, Plot plot) { + this.player = player; + this.from = from; + this.plot = plot; + } + + public static HandlerList getHandlers() { + return handlers; + } + + + /** + * Get the from location + * + * @return Location + */ + public Location getFrom() { + return this.from; + } + + /** + * Get the plot involved + * + * @return Plot + */ + public Plot getPlot() { + return this.plot; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotClearEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotClearEvent.java new file mode 100644 index 000000000..47e5ddcf8 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotClearEvent.java @@ -0,0 +1,52 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.event.Cancellable; +import cn.nukkit.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 { + + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; + public PlotClearEvent(Plot plot) { + super(plot); + } + + public static HandlerList getHandlers() { + 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 boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(boolean b) { + this.cancelled = b; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotComponentSetEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotComponentSetEvent.java new file mode 100644 index 000000000..5a3515342 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotComponentSetEvent.java @@ -0,0 +1,52 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.event.HandlerList; +import com.intellectualcrafters.plot.object.Plot; +import com.intellectualcrafters.plot.object.PlotId; + +/** + * Called when a plot component is set + * + */ +public class PlotComponentSetEvent extends PlotEvent { + + private static final HandlerList handlers = new HandlerList(); + private final String component; + + public PlotComponentSetEvent(Plot plot, String component) { + super(plot); + this.component = component; + } + + public static HandlerList getHandlers() { + 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; + } + + /** + * Get the component which was set + * + * @return Component name + */ + public String getComponent() { + return this.component; + } + +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotDeleteEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotDeleteEvent.java new file mode 100644 index 000000000..223eb5251 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotDeleteEvent.java @@ -0,0 +1,41 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.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 { + + private static final HandlerList handlers = new HandlerList(); + + public PlotDeleteEvent(Plot plot) { + super(plot); + } + + public static HandlerList getHandlers() { + 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; + } + +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotEvent.java new file mode 100644 index 000000000..21f90f3bf --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotEvent.java @@ -0,0 +1,18 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.event.Event; +import com.intellectualcrafters.plot.object.Plot; + +public abstract class PlotEvent extends Event { + + private final Plot plot; + + public PlotEvent(Plot plot) { + this.plot = plot; + } + + public final Plot getPlot() { + return this.plot; + } + +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotFlagAddEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotFlagAddEvent.java new file mode 100644 index 000000000..540f1dad9 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotFlagAddEvent.java @@ -0,0 +1,51 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.event.Cancellable; +import cn.nukkit.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 final 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(Flag flag, Plot plot) { + super(plot); + this.flag = flag; + } + + public static HandlerList getHandlers() { + return handlers; + } + + /** + * Get the flag involved. + * + * @return Flag + */ + public Flag getFlag() { + return this.flag; + } + + @Override + public final boolean isCancelled() { + return this.cancelled; + } + + @Override + public final void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotFlagRemoveEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotFlagRemoveEvent.java new file mode 100644 index 000000000..3baa8b462 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotFlagRemoveEvent.java @@ -0,0 +1,51 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.event.Cancellable; +import cn.nukkit.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 final 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(Flag flag, Plot plot) { + super(plot); + this.flag = flag; + } + + public static HandlerList getHandlers() { + return handlers; + } + + /** + * Get the flag involved + * + * @return Flag + */ + public Flag getFlag() { + return this.flag; + } + + @Override + public final boolean isCancelled() { + return this.cancelled; + } + + @Override + public final void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotMergeEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotMergeEvent.java new file mode 100644 index 000000000..960eb4c03 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotMergeEvent.java @@ -0,0 +1,56 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.event.Cancellable; +import cn.nukkit.event.HandlerList; +import cn.nukkit.level.Level; +import com.intellectualcrafters.plot.object.Plot; +import com.intellectualcrafters.plot.object.PlotId; +import java.util.ArrayList; + +public class PlotMergeEvent extends PlotEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + private final ArrayList plots; + private final Level world; + private boolean cancelled; + + /** + * 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(Level world, Plot plot, ArrayList plots) { + super(plot); + this.world = world; + this.plots = plots; + } + + public static HandlerList getHandlers() { + return handlers; + } + + /** + * Get the plots being added. + * + * @return Plot + */ + public ArrayList getPlots() { + return this.plots; + } + + public Level getLevel() { + return this.world; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(boolean b) { + this.cancelled = b; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotRateEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotRateEvent.java new file mode 100644 index 000000000..de9a9f0b5 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotRateEvent.java @@ -0,0 +1,36 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.event.HandlerList; +import com.intellectualcrafters.plot.object.Plot; +import com.intellectualcrafters.plot.object.PlotPlayer; +import com.intellectualcrafters.plot.object.Rating; + +public class PlotRateEvent extends PlotEvent { + + private static final HandlerList handlers = new HandlerList(); + private final PlotPlayer rater; + private Rating rating; + + public PlotRateEvent(PlotPlayer rater, Rating rating, Plot plot) { + super(plot); + this.rater = rater; + this.rating = rating; + } + + public static HandlerList getHandlers() { + return handlers; + } + + public PlotPlayer getRater() { + return this.rater; + } + + public Rating getRating() { + return this.rating; + } + + public void setRating(Rating rating) { + this.rating = rating; + } + +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotUnlinkEvent.java b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotUnlinkEvent.java new file mode 100644 index 000000000..4ddc2e6ee --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/events/PlotUnlinkEvent.java @@ -0,0 +1,61 @@ +package com.plotsquared.nukkit.events; + +import cn.nukkit.event.Cancellable; +import cn.nukkit.event.Event; +import cn.nukkit.event.HandlerList; +import cn.nukkit.level.Level; +import com.intellectualcrafters.plot.object.PlotArea; +import com.intellectualcrafters.plot.object.PlotId; +import java.util.ArrayList; + +public class PlotUnlinkEvent extends Event implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + private final ArrayList plots; + private final Level world; + private final PlotArea area; + private boolean cancelled; + + /** + * 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(Level world, PlotArea area, ArrayList plots) { + this.plots = plots; + this.world = world; + this.area = area; + } + + public static HandlerList getHandlers() { + return handlers; + } + + /** + * Get the plots involved. + * + * @return The {@link PlotId}'s of the plots involved + */ + public ArrayList getPlots() { + return this.plots; + } + + public Level getLevel() { + return this.world; + } + + public PlotArea getArea() { + return this.area; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(boolean b) { + this.cancelled = b; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/generator/NukkitAugmentedGenerator.java b/Nukkit/src/main/java/com/plotsquared/nukkit/generator/NukkitAugmentedGenerator.java new file mode 100644 index 000000000..5ba60b4f6 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/generator/NukkitAugmentedGenerator.java @@ -0,0 +1,47 @@ +package com.plotsquared.nukkit.generator; + +import cn.nukkit.event.EventHandler; +import cn.nukkit.event.Listener; +import cn.nukkit.event.level.ChunkLoadEvent; +import cn.nukkit.level.Level; +import cn.nukkit.level.format.FullChunk; +import com.intellectualcrafters.plot.PS; +import com.intellectualcrafters.plot.generator.AugmentedUtils; +import com.plotsquared.nukkit.NukkitMain; +import java.util.concurrent.ConcurrentHashMap; + +public class NukkitAugmentedGenerator implements Listener { + + private static NukkitAugmentedGenerator generator; + private static ConcurrentHashMap generators = new ConcurrentHashMap<>(); + + private NukkitAugmentedGenerator(NukkitMain plugin) { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + public static NukkitAugmentedGenerator get(Level level) { + NukkitAugmentedGenerator current = generators.get(level.getName()); + if (current != null) { + return current; + } + if (generator == null) { + NukkitMain plugin = ((NukkitMain) PS.get().IMP); + generator = new NukkitAugmentedGenerator(plugin); + } + generators.put(level.getName(), generator); + return generator; + } + + @EventHandler + private void onChunkLoad(ChunkLoadEvent event) { + Level level = event.getLevel(); + generator = generators.get(level.getName()); + if (generator != null) { + generator.populate(level, event.getChunk()); + } + } + + private void populate(Level world, FullChunk chunk) { + AugmentedUtils.generate(world.getName(), chunk.getX(), chunk.getZ(), null); + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/generator/NukkitPlotGenerator.java b/Nukkit/src/main/java/com/plotsquared/nukkit/generator/NukkitPlotGenerator.java new file mode 100644 index 000000000..d37609549 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/generator/NukkitPlotGenerator.java @@ -0,0 +1,203 @@ +package com.plotsquared.nukkit.generator; + +import cn.nukkit.level.format.generic.BaseFullChunk; +import cn.nukkit.level.generator.Generator; +import cn.nukkit.math.NukkitRandom; +import cn.nukkit.math.Vector3; +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.Location; +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.block.ScopedLocalBlockQueue; +import com.plotsquared.nukkit.util.NukkitUtil; +import com.plotsquared.nukkit.util.block.NukkitWrappedChunk; +import java.util.Map; + +public class NukkitPlotGenerator extends Generator implements GeneratorWrapper { + + private final PseudoRandom random = new PseudoRandom(); + private final IndependentPlotGenerator plotGenerator; + private final Generator platformGenerator; + private final boolean full; + private final String world; + private final Map settings; + private boolean loaded = false; + private cn.nukkit.level.ChunkManager chunkManager; + private final NukkitWrappedChunk chunkSetter; + + public NukkitPlotGenerator(Map map) { + if (map == null) { + throw new IllegalArgumentException("options may not be null!"); + } + this.settings = map; + MainUtil.initCache(); + this.world = map.get("world").toString(); + if (map.containsKey("generator")) { + final Generator cg = (Generator) map.get("generator"); + if (cg instanceof NukkitPlotGenerator) { + throw new IllegalArgumentException("Generator: " + cg.getClass().getName() + " is already a BukkitPlotGenerator!"); + } + this.full = false; + PS.debug("BukkitPlotGenerator does not fully support: " + cg); + this.platformGenerator = cg; + this.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 ScopedLocalBlockQueue result, PlotArea settings, PseudoRandom random) { + Location min = result.getMin(); + int cx = min.getX() >> 4; + int cz = min.getZ() >> 4; + cg.generateChunk(cx, cz); + cg.populateChunk(cx, cz); + } + }; + chunkSetter = new NukkitWrappedChunk(world, null); + MainUtil.initCache(); + } else { + this.plotGenerator = (IndependentPlotGenerator) map.get("plot-generator"); + this.platformGenerator = this; + this.full = true; + chunkSetter = new NukkitWrappedChunk(world, null); + } + PS.get().loadWorld(world, this); + } + + @Override + public void augment(PlotArea area) { + NukkitAugmentedGenerator.get(NukkitUtil.getWorld(area.worldname)); + } + + @Override + public boolean isFull() { + return this.full; + } + + @Override + public IndependentPlotGenerator getPlotGenerator() { + return this.plotGenerator; + } + + @Override + public Generator getPlatformGenerator() { + return this.platformGenerator; + } + + @Override + public String toString() { + if (this.platformGenerator == this) { + return this.plotGenerator.getName(); + } + if (this.platformGenerator == null) { + return "null"; + } else { + return this.platformGenerator.getClass().getName(); + } + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + return toString().equals(obj.toString()) || toString().equals(obj.getClass().getName()); + } + + @Override + public int getId() { + return 1; + } + + @Override + public void init(cn.nukkit.level.ChunkManager chunkManager, NukkitRandom nukkitRandom) { + this.chunkManager = chunkManager; + if (getPlatformGenerator() != this) { + getPlatformGenerator().init(chunkManager, nukkitRandom); + } + } + + @Override + public void generateChunk(int cx, int cz) { + if (getPlatformGenerator() != this) { + getPlatformGenerator().generateChunk(cx, cz); + } else { + BaseFullChunk chunk = this.chunkManager.getChunk(cx, cz); + // Load if improperly loaded + if (!this.loaded) { + PS.get().loadWorld(world, this); + this.loaded = true; + } + chunkSetter.init(chunk); + // Set random seed + this.random.state = cx << 16 | cz & 0xFFFF; + // Process the chunk + if (ChunkManager.preProcessChunk(chunkSetter)) { + return; + } + PlotArea area = PS.get().getPlotArea(world, null); + try { + this.plotGenerator.generateChunk(this.chunkSetter, area, this.random); + } catch (Throwable e) { + // Recover from generator error + e.printStackTrace(); + } + ChunkManager.postProcessChunk(chunkSetter); + } + } + + @Override + public void populateChunk(int x, int z) { + if (getPlatformGenerator() != this) { + getPlatformGenerator().populateChunk(x, z); + } else { + // No populating + } + } + + @Override + public Map getSettings() { + return settings; + } + + @Override + public String getName() { + return plotGenerator.getName(); + } + + @Override + public Vector3 getSpawn() { + return new Vector3(0, 61, 0); + } + + @Override + public cn.nukkit.level.ChunkManager getChunkManager() { + return chunkManager; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/listeners/PlayerEvents.java b/Nukkit/src/main/java/com/plotsquared/nukkit/listeners/PlayerEvents.java new file mode 100644 index 000000000..1736d610a --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/listeners/PlayerEvents.java @@ -0,0 +1,1321 @@ +package com.plotsquared.nukkit.listeners; + +import cn.nukkit.Player; +import cn.nukkit.block.Block; +import cn.nukkit.command.CommandSender; +import cn.nukkit.entity.Entity; +import cn.nukkit.entity.EntityCreature; +import cn.nukkit.entity.EntityHanging; +import cn.nukkit.entity.EntityHuman; +import cn.nukkit.entity.EntityLiving; +import cn.nukkit.entity.item.EntityPotion; +import cn.nukkit.entity.item.EntityVehicle; +import cn.nukkit.entity.mob.EntityMob; +import cn.nukkit.entity.passive.EntityAnimal; +import cn.nukkit.entity.passive.EntityWaterAnimal; +import cn.nukkit.entity.projectile.EntityProjectile; +import cn.nukkit.event.Cancellable; +import cn.nukkit.event.Event; +import cn.nukkit.event.EventHandler; +import cn.nukkit.event.EventPriority; +import cn.nukkit.event.Listener; +import cn.nukkit.event.block.BlockBreakEvent; +import cn.nukkit.event.block.BlockBurnEvent; +import cn.nukkit.event.block.BlockFormEvent; +import cn.nukkit.event.block.BlockGrowEvent; +import cn.nukkit.event.block.BlockPlaceEvent; +import cn.nukkit.event.block.BlockSpreadEvent; +import cn.nukkit.event.block.BlockUpdateEvent; +import cn.nukkit.event.entity.EntityBlockChangeEvent; +import cn.nukkit.event.entity.EntityCombustByEntityEvent; +import cn.nukkit.event.entity.EntityDamageByEntityEvent; +import cn.nukkit.event.entity.EntityDamageEvent; +import cn.nukkit.event.entity.EntityExplodeEvent; +import cn.nukkit.event.entity.EntitySpawnEvent; +import cn.nukkit.event.entity.ExplosionPrimeEvent; +import cn.nukkit.event.entity.ProjectileHitEvent; +import cn.nukkit.event.entity.ProjectileLaunchEvent; +import cn.nukkit.event.inventory.InventoryCloseEvent; +import cn.nukkit.event.player.PlayerBucketEmptyEvent; +import cn.nukkit.event.player.PlayerBucketFillEvent; +import cn.nukkit.event.player.PlayerChatEvent; +import cn.nukkit.event.player.PlayerCommandPreprocessEvent; +import cn.nukkit.event.player.PlayerInteractEvent; +import cn.nukkit.event.player.PlayerJoinEvent; +import cn.nukkit.event.player.PlayerMoveEvent; +import cn.nukkit.event.player.PlayerQuitEvent; +import cn.nukkit.event.player.PlayerRespawnEvent; +import cn.nukkit.event.player.PlayerTeleportEvent; +import cn.nukkit.event.potion.PotionCollideEvent; +import cn.nukkit.event.redstone.RedstoneUpdateEvent; +import cn.nukkit.metadata.MetadataValue; +import cn.nukkit.plugin.Plugin; +import com.google.common.base.Optional; +import com.intellectualcrafters.plot.PS; +import com.intellectualcrafters.plot.config.C; +import com.intellectualcrafters.plot.config.Settings; +import com.intellectualcrafters.plot.flag.Flags; +import com.intellectualcrafters.plot.flag.IntegerFlag; +import com.intellectualcrafters.plot.object.Location; +import com.intellectualcrafters.plot.object.Plot; +import com.intellectualcrafters.plot.object.PlotArea; +import com.intellectualcrafters.plot.object.PlotBlock; +import com.intellectualcrafters.plot.object.PlotId; +import com.intellectualcrafters.plot.object.PlotPlayer; +import com.intellectualcrafters.plot.object.StringWrapper; +import com.intellectualcrafters.plot.util.EventUtil; +import com.intellectualcrafters.plot.util.MainUtil; +import com.intellectualcrafters.plot.util.MathMan; +import com.intellectualcrafters.plot.util.Permissions; +import com.intellectualcrafters.plot.util.RegExUtil; +import com.intellectualcrafters.plot.util.TaskManager; +import com.intellectualcrafters.plot.util.UUIDHandler; +import com.plotsquared.listener.PlotListener; +import com.plotsquared.nukkit.object.NukkitPlayer; +import com.plotsquared.nukkit.util.NukkitUtil; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.UUID; +import java.util.regex.Pattern; + +public class PlayerEvents extends PlotListener implements Listener { + + private boolean pistonBlocks = true; + // To prevent recursion + private boolean tmpTeleport = true; + + // TODO fix this + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onPhysicsEvent(BlockUpdateEvent event) { + if (event instanceof RedstoneUpdateEvent) { + Block block = event.getBlock(); + Location loc = NukkitUtil.getLocation(block.getLocation()); + PlotArea area = loc.getPlotArea(); + if (area == null) { + return; + } + Plot plot = area.getOwnedPlotAbs(loc); + if (plot == null) { + return; + } + if (Flags.REDSTONE.isFalse(plot)) { + event.setCancelled(true); + return; + } + if (Settings.Redstone.DISABLE_OFFLINE) { + if (UUIDHandler.getPlayer(plot.owner) == null) { + boolean disable = true; + for (UUID trusted : plot.getTrusted()) { + if (UUIDHandler.getPlayer(trusted) != null) { + disable = false; + break; + } + } + if (disable) { + event.setCancelled(true); + return; + } + } + } + if (Settings.Redstone.DISABLE_UNOCCUPIED) { + for (Map.Entry entry : UUIDHandler.getPlayers().entrySet()) { + if (plot.equals(entry.getValue().getCurrentPlot())) { + return; + } + } + event.setCancelled(true); + } + } else { + Block block = event.getBlock(); + Location loc = NukkitUtil.getLocation(block.getLocation()); + PlotArea area = loc.getPlotArea(); + if (area == null) { + return; + } + Plot plot = area.getOwnedPlotAbs(loc); + if (plot == null) { + return; + } + if (Flags.DISABLE_PHYSICS.isFalse(plot)) { + event.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onEntityCombustByEntity(EntityCombustByEntityEvent event) { + EntityDamageByEntityEvent eventChange = new EntityDamageByEntityEvent(event.getCombuster(), event.getEntity(), EntityDamageEvent.CAUSE_FIRE_TICK, event.getDuration()); + onEntityDamageByEntityEvent(eventChange); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onEntityDamageByEntityEvent(EntityDamageEvent event) { + if (event instanceof EntityDamageByEntityEvent) { + EntityDamageByEntityEvent specific = (EntityDamageByEntityEvent) event; + Entity damager = specific.getDamager(); + Location l = NukkitUtil.getLocation(damager); + if (!PS.get().hasPlotArea(l.getWorld())) { + return; + } + Entity victim = event.getEntity(); + if (!entityDamage(damager, victim)) { + event.setCancelled(true); + } + } + } + + @EventHandler + public void onProjectileLaunch(ProjectileLaunchEvent event) { + EntityProjectile entity = event.getEntity(); + if (!(entity instanceof EntityPotion)) { + return; + } + Entity shooter = entity.shootingEntity; + if (!(shooter instanceof Player)) { + return; + } + Location l = NukkitUtil.getLocation(entity); + if (!PS.get().hasPlotArea(l.getWorld())) { + return; + } + PlotPlayer pp = NukkitUtil.getPlayer((Player) shooter); + Plot plot = l.getOwnedPlot(); + if (plot != null && !plot.isAdded(pp.getUUID())) { + kill(entity, event); + } + } + + @EventHandler + public boolean onProjectileHit(ProjectileHitEvent event) { + EntityProjectile entity = (EntityProjectile) event.getEntity(); + Location loc = NukkitUtil.getLocation(entity); + if (!PS.get().hasPlotArea(loc.getWorld())) { + return true; + } + PlotArea area = loc.getPlotArea(); + if (area == null) { + return true; + } + Plot plot = area.getPlotAbs(loc); + Entity shooter = entity.shootingEntity; + if (shooter instanceof Player) { + PlotPlayer pp = NukkitUtil.getPlayer((Player) shooter); + if (plot == null) { + if (!Permissions.hasPermission(pp, C.PERMISSION_PROJECTILE_UNOWNED)) { + kill(entity, event); + return false; + } + return true; + } + if (plot.isAdded(pp.getUUID()) || Permissions.hasPermission(pp, C.PERMISSION_PROJECTILE_OTHER)) { + return true; + } + kill(entity, event); + return false; + } + if (shooter == null) { + kill(entity, event); + return false; + } + return true; + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void playerCommand(PlayerCommandPreprocessEvent event) { + String msg = event.getMessage().toLowerCase().replaceAll("/", "").trim(); + if (msg.isEmpty()) { + return; + } + String[] split = msg.split(" "); + Player player = event.getPlayer(); + PlotPlayer pp = NukkitUtil.getPlayer(player); + Plot plot = pp.getCurrentPlot(); + if (plot == null) { + return; + } + Optional> flag = plot.getFlag(Flags.BLOCKED_CMDS); + if (flag.isPresent() && !Permissions.hasPermission(pp, C.PERMISSION_ADMIN_INTERACT_BLOCKED_CMDS)) { + List blocked_cmds = flag.get(); + for (String s : blocked_cmds) { + Pattern pattern; + if (!RegExUtil.compiledPatterns.containsKey(s)) { + RegExUtil.compiledPatterns.put(s, pattern = Pattern.compile(s)); + } else { + pattern = RegExUtil.compiledPatterns.get(s); + } + if (pattern.matcher(msg).matches()) { + String perm; + if (plot.isAdded(pp.getUUID())) { + perm = "plots.admin.command.blocked-cmds.shared"; + } else { + perm = "plots.admin.command.blocked-cmds.other"; + } + if (!Permissions.hasPermission(pp, perm)) { + MainUtil.sendMessage(pp, C.COMMAND_BLOCKED); + event.setCancelled(true); + } + return; + } + } + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onConnect(PlayerJoinEvent event) { + final Player player = event.getPlayer(); + NukkitUtil.getPlayer(event.getPlayer()).unregister(); + final PlotPlayer pp = NukkitUtil.getPlayer(player); + // Now + String name = pp.getName(); + StringWrapper sw = new StringWrapper(name); + UUID uuid = pp.getUUID(); + UUIDHandler.add(sw, uuid); + + Location loc = pp.getLocation(); + PlotArea area = loc.getPlotArea(); + if (area != null) { + Plot plot = area.getPlot(loc); + if (plot != null) { + plotEntry(pp, plot); + } + } + // Delayed + + // Async + TaskManager.runTaskLaterAsync(new Runnable() { + @Override + public void run() { + if (!player.hasPlayedBefore() && player.isOnline()) { + player.save(); + } + EventUtil.manager.doJoinTask(pp); + } + }, 20); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void playerRespawn(PlayerRespawnEvent event) { + Player player = event.getPlayer(); + PlotPlayer pp = NukkitUtil.getPlayer(player); + EventUtil.manager.doRespawnTask(pp); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onTeleport(PlayerTeleportEvent event) { + if (event.getTo() == null || event.getFrom() == null) { + NukkitUtil.getPlayer(event.getPlayer()).deleteMeta("location"); + NukkitUtil.getPlayer(event.getPlayer()).deleteMeta("lastplot"); + return; + } + cn.nukkit.level.Location from = event.getFrom(); + cn.nukkit.level.Location to = event.getTo(); + int x2; + if (MathMan.roundInt(from.getX()) != (x2 = MathMan.roundInt(to.getX()))) { + Player player = event.getPlayer(); + PlotPlayer pp = NukkitUtil.getPlayer(player); + // Cancel teleport + TaskManager.TELEPORT_QUEUE.remove(pp.getName()); + // Set last location + Location loc = NukkitUtil.getLocation(to); + pp.setMeta("location", loc); + PlotArea area = loc.getPlotArea(); + if (area == null) { + pp.deleteMeta("lastplot"); + return; + } + Plot now = area.getPlot(loc); + Plot lastPlot = pp.getMeta("lastplot"); + if (now == null) { + if (lastPlot != null && !plotExit(pp, lastPlot) && this.tmpTeleport) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_EXIT_DENIED); + this.tmpTeleport = false; + if (lastPlot.equals(NukkitUtil.getLocation(from).getPlot())) { + player.teleport(from); + } else { + player.teleport(player.getLevel().getSpawnLocation()); + } + this.tmpTeleport = true; + event.setCancelled(true); + return; + } + } else if (now.equals(lastPlot)) { + return; + } else if (!plotEntry(pp, now) && this.tmpTeleport) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_ENTRY_DENIED); + this.tmpTeleport = false; + to.setComponents(from.getX(), from.getY(), from.getZ()); + player.teleport(event.getTo()); + this.tmpTeleport = true; + return; + } + Integer border = area.getBorder(); + if (x2 > border) { + to.setComponents(border - 4, to.getY(), to.getZ()); + this.tmpTeleport = false; + player.teleport(event.getTo()); + this.tmpTeleport = true; + MainUtil.sendMessage(pp, C.BORDER); + return; + } + if (x2 < -border) { + to.setComponents(-border + 4, to.getY(), to.getZ()); + this.tmpTeleport = false; + player.teleport(event.getTo()); + this.tmpTeleport = true; + MainUtil.sendMessage(pp, C.BORDER); + return; + } + return; + } + int z2; + if (MathMan.roundInt(from.getZ()) != (z2 = MathMan.roundInt(to.getZ()))) { + Player player = event.getPlayer(); + PlotPlayer pp = NukkitUtil.getPlayer(player); + // Cancel teleport + TaskManager.TELEPORT_QUEUE.remove(pp.getName()); + // Set last location + Location loc = NukkitUtil.getLocation(to); + pp.setMeta("location", loc); + PlotArea area = loc.getPlotArea(); + if (area == null) { + pp.deleteMeta("lastplot"); + return; + } + Plot now = area.getPlot(loc); + Plot lastPlot = pp.getMeta("lastplot"); + if (now == null) { + if (lastPlot != null && !plotExit(pp, lastPlot) && this.tmpTeleport) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_EXIT_DENIED); + this.tmpTeleport = false; + if (lastPlot.equals(NukkitUtil.getLocation(from).getPlot())) { + player.teleport(from); + } else { + player.teleport(player.getLevel().getSpawnLocation()); + } + this.tmpTeleport = true; + event.setCancelled(true); + return; + } + } else if (now.equals(lastPlot)) { + return; + } else if (!plotEntry(pp, now) && this.tmpTeleport) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_ENTRY_DENIED); + this.tmpTeleport = false; + player.teleport(from); + to.setComponents(from.getX(), from.getY(), from.getZ()); + player.teleport(event.getTo()); + this.tmpTeleport = true; + return; + } + Integer border = area.getBorder(); + if (z2 > border) { + to.setComponents(to.getX(), to.getY(), border - 4); + this.tmpTeleport = false; + player.teleport(event.getTo()); + this.tmpTeleport = true; + MainUtil.sendMessage(pp, C.BORDER); + } else if (z2 < -border) { + to.setComponents(to.getX(), to.getY(), -border + 4); + this.tmpTeleport = false; + player.teleport(event.getTo()); + this.tmpTeleport = true; + MainUtil.sendMessage(pp, C.BORDER); + } + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void playerMove(PlayerMoveEvent event) { + cn.nukkit.level.Location from = event.getFrom(); + cn.nukkit.level.Location to = event.getTo(); + int x2; + if (MathMan.roundInt(from.getX()) != (x2 = MathMan.roundInt(to.getX()))) { + Player player = event.getPlayer(); + PlotPlayer pp = NukkitUtil.getPlayer(player); + // Cancel teleport + TaskManager.TELEPORT_QUEUE.remove(pp.getName()); + // Set last location + Location loc = NukkitUtil.getLocation(to); + pp.setMeta("location", loc); + PlotArea area = loc.getPlotArea(); + if (area == null) { + pp.deleteMeta("lastplot"); + return; + } + Plot now = area.getPlot(loc); + Plot lastPlot = pp.getMeta("lastplot"); + if (now == null) { + if (lastPlot != null && !plotExit(pp, lastPlot) && this.tmpTeleport) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_EXIT_DENIED); + this.tmpTeleport = false; + if (lastPlot.equals(NukkitUtil.getLocation(from).getPlot())) { + player.teleport(from); + } else { + player.teleport(player.getLevel().getSpawnLocation()); + } + this.tmpTeleport = true; + event.setCancelled(true); + return; + } + } else if (now.equals(lastPlot)) { + return; + } else if (!plotEntry(pp, now) && this.tmpTeleport) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_ENTRY_DENIED); + this.tmpTeleport = false; + to.setComponents(from.getX(), from.getY(), from.getZ()); + player.teleport(event.getTo()); + this.tmpTeleport = true; + return; + } + Integer border = area.getBorder(); + if (x2 > border) { + to.setComponents(border - 4, to.getY(), to.getZ()); + this.tmpTeleport = false; + player.teleport(event.getTo()); + this.tmpTeleport = true; + MainUtil.sendMessage(pp, C.BORDER); + return; + } + if (x2 < -border) { + to.setComponents(-border + 4, to.getY(), to.getZ()); + this.tmpTeleport = false; + player.teleport(event.getTo()); + this.tmpTeleport = true; + MainUtil.sendMessage(pp, C.BORDER); + return; + } + return; + } + int z2; + if (MathMan.roundInt(from.getZ()) != (z2 = MathMan.roundInt(to.getZ()))) { + Player player = event.getPlayer(); + PlotPlayer pp = NukkitUtil.getPlayer(player); + // Cancel teleport + TaskManager.TELEPORT_QUEUE.remove(pp.getName()); + // Set last location + Location loc = NukkitUtil.getLocation(to); + pp.setMeta("location", loc); + PlotArea area = loc.getPlotArea(); + if (area == null) { + pp.deleteMeta("lastplot"); + return; + } + Plot now = area.getPlot(loc); + Plot lastPlot = pp.getMeta("lastplot"); + if (now == null) { + if (lastPlot != null && !plotExit(pp, lastPlot) && this.tmpTeleport) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_EXIT_DENIED); + this.tmpTeleport = false; + if (lastPlot.equals(NukkitUtil.getLocation(from).getPlot())) { + player.teleport(from); + } else { + player.teleport(player.getLevel().getSpawnLocation()); + } + this.tmpTeleport = true; + event.setCancelled(true); + return; + } + } else if (now.equals(lastPlot)) { + return; + } else if (!plotEntry(pp, now) && this.tmpTeleport) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_ENTRY_DENIED); + this.tmpTeleport = false; + player.teleport(from); + to.setComponents(from.getX(), from.getY(), from.getZ()); + player.teleport(event.getTo()); + this.tmpTeleport = true; + return; + } + Integer border = area.getBorder(); + if (z2 > border) { + to.setComponents(to.getX(), to.getY(), border - 4); + this.tmpTeleport = false; + player.teleport(event.getTo()); + this.tmpTeleport = true; + MainUtil.sendMessage(pp, C.BORDER); + } else if (z2 < -border) { + to.setComponents(to.getX(), to.getY(), -border + 4); + this.tmpTeleport = false; + player.teleport(event.getTo()); + this.tmpTeleport = true; + MainUtil.sendMessage(pp, C.BORDER); + } + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onChat(PlayerChatEvent event) { + PlotPlayer plotPlayer = NukkitUtil.getPlayer(event.getPlayer()); + Location location = plotPlayer.getLocation(); + PlotArea area = location.getPlotArea(); + if (area == null || (!area.PLOT_CHAT != plotPlayer.getAttribute("chat"))) { + return; + } + Plot plot = area.getPlot(location); + if (plot == null) { + return; + } + event.setCancelled(true); + String message = event.getMessage(); + String format = C.PLOT_CHAT_FORMAT.s(); + String sender = event.getPlayer().getDisplayName(); + PlotId id = plot.getId(); + Set recipients = event.getRecipients(); + recipients.clear(); + for (Entry entry : UUIDHandler.getPlayers().entrySet()) { + PlotPlayer pp = entry.getValue(); + if (pp.getAttribute("chatspy")) { + String spy = event.getFormat(); + spy = String.format(spy, sender, message); + pp.sendMessage(spy); + } else { + Plot current = pp.getCurrentPlot(); + if (current != null && current.getBasePlot(false).equals(plot)) { + recipients.add(((NukkitPlayer) pp).player); + } + } + } + String partial = C.color(format.replace("%plot_id%", id.x + ";" + id.y).replace("%sender%", sender)); + String full = partial.replace("%msg%", message); + for (CommandSender receiver : recipients) { + receiver.sendMessage(full); + } + } + +@EventHandler(priority = EventPriority.LOWEST) +public void blockDestroy(BlockBreakEvent event) { + Player player = event.getPlayer(); + Location location = NukkitUtil.getLocation(event.getBlock().getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + Plot plot = area.getPlotAbs(location); + if (plot != null) { + PlotPlayer plotPlayer = NukkitUtil.getPlayer(player); + if (event.getBlock().getY() == 0) { + if (!Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_DESTROY_GROUNDLEVEL)) { + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_DESTROY_GROUNDLEVEL); + event.setCancelled(true); + return; + } + } + if (!plot.hasOwner()) { + if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_DESTROY_UNOWNED)) { + return; + } + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_DESTROY_UNOWNED); + event.setCancelled(true); + return; + } + if (!plot.isAdded(plotPlayer.getUUID())) { + Optional> destroy = plot.getFlag(Flags.BREAK); + Block block = event.getBlock(); + if (destroy.isPresent() && destroy.get() + .contains(PlotBlock.get((short) block.getId(), block.getDamage()))) { + return; + } + if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_DESTROY_OTHER)) { + return; + } + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_DESTROY_OTHER); + event.setCancelled(true); + } else if (Settings.Done.RESTRICT_BUILDING && plot.getFlags().containsKey(Flags.DONE)) { + if (!Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_BUILD_OTHER)) { + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); + event.setCancelled(true); + return; + } + } + return; + } + PlotPlayer pp = NukkitUtil.getPlayer(player); + if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_DESTROY_ROAD)) { + return; + } + if (PS.get().worldedit != null && pp.getAttribute("worldedit")) { + if (player.getInventory().getItemInHand().getId() == PS.get().worldedit.getConfiguration().wandItem) { + return; + } + } + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_DESTROY_ROAD); + event.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBigBoom(ExplosionPrimeEvent event) { + Entity entity = event.getEntity(); + Location location = NukkitUtil.getLocation(entity); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + final Plot finalPlot = area.getOwnedPlot(location); + if (!entity.hasMetadata("plot")) { + entity.setMetadata("plot", new MetadataValue((Plugin) PS.get().IMP) { + private Plot plot = finalPlot; + @Override + public Object value() { + return plot; + } + @Override + public void invalidate() { + plot = null; + } + }); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBigBoom(EntityExplodeEvent event) { + Location location = NukkitUtil.getLocation(event.getPosition()); + PlotArea area = location.getPlotArea(); + if (area == null) { + if (!PS.get().hasPlotArea(location.getWorld())) { + return; + } + Iterator iterator = event.getBlockList().iterator(); + while (iterator.hasNext()) { + iterator.next(); + if (location.getPlotArea() != null) { + iterator.remove(); + } + } + return; + } + Plot plot = area.getOwnedPlot(location); + if (plot != null) { + if (Flags.EXPLOSION.isTrue(plot)) { + List meta = event.getEntity().getMetadata("plot"); + Plot origin; + if (meta.isEmpty()) { + origin = plot; + } else { + origin = (Plot) meta.get(0).value(); + } + Iterator iterator = event.getBlockList().iterator(); + while (iterator.hasNext()) { + Block block = iterator.next(); + location = NukkitUtil.getLocation(block.getLocation()); + if (!area.contains(location.getX(), location.getZ()) || !origin.equals(area.getOwnedPlot(location))) { + iterator.remove(); + } + } + return; + } + } + event.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onEntityBlockForm(BlockFormEvent event) { + String world = event.getBlock().getLevel().getName(); + if (!PS.get().hasPlotArea(world)) { + return; + } + if (NukkitUtil.getLocation(event.getBlock().getLocation()).getPlotArea() != null) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockSpread(BlockSpreadEvent event) { + Block block = event.getBlock(); + Location location = NukkitUtil.getLocation(block.getLocation()); + if (location.isPlotRoad()) { + event.setCancelled(true); + return; + } + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + Plot plot = area.getOwnedPlot(location); + if (plot == null) { + return; + } + Block source = event.getSource(); + switch (source.getId()) { + case 2: + if (Flags.GRASS_GROW.isFalse(plot)) { + event.setCancelled(true); + } + break; + case 110: + if (Flags.MYCEL_GROW.isFalse(plot)) { + event.setCancelled(true); + } + break; + case 106: + if (Flags.VINE_GROW.isFalse(plot)) { + event.setCancelled(true); + } + break; + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onGrow(BlockGrowEvent event) { + Block b = event.getBlock(); + Location location = NukkitUtil.getLocation(b.getLocation()); + if (location.isUnownedPlotArea()) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + PlotPlayer pp = NukkitUtil.getPlayer(player); + PlotArea area = pp.getPlotAreaAbs(); + if (area == null) { + return; + } + switch (event.getAction()) { + case PlayerInteractEvent.RIGHT_CLICK_BLOCK: + case PlayerInteractEvent.LEFT_CLICK_BLOCK: + case PlayerInteractEvent.PHYSICAL: { + Plot plot = pp.getCurrentPlot(); + if (plot == null || !plot.isAdded(pp.getUUID())) { + Block block = event.getBlock(); + if (block != null) { + if (plot != null && Flags.USE.contains(plot, PlotBlock.get(block.getId(), block.getDamage()))) { + return; + } + } + if (plot == null) { + if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_INTERACT_ROAD.s(), true)) { + return; + } + } else if (!plot.hasOwner()) { + if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_INTERACT_UNOWNED.s(), true)) { + return; + } + } else if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_INTERACT_OTHER.s(), true)) { + return; + } + event.setCancelled(true); + return; + } + return; + } + case PlayerInteractEvent.LEFT_CLICK_AIR: + case PlayerInteractEvent.RIGHT_CLICK_AIR: { + Plot plot = pp.getCurrentPlot(); + if (plot == null || !plot.isAdded(pp.getUUID())) { + if (plot == null) { + if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_INTERACT_ROAD.s(), true)) { + return; + } + } else if (!plot.hasOwner()) { + if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_INTERACT_UNOWNED.s(), true)) { + return; + } + } else if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_INTERACT_OTHER.s(), true)) { + return; + } + event.setCancelled(true); + return; + } + return; + } + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void creatureSpawnEvent(EntitySpawnEvent event) { + Entity entity = event.getEntity(); + Location location = NukkitUtil.getLocation(entity.getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + Plot plot = area.getOwnedPlotAbs(location); + if (plot == null) { + if (!area.MOB_SPAWNING) { + kill(entity, event); + } + return; + } + if (checkEntity(entity, plot)) { + kill(entity, event); + } + } + + private void kill(Entity entity, Event event) { + if (event instanceof Cancellable) { + event.setCancelled(true); + } + entity.kill(); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onEntityFall(EntityBlockChangeEvent event) { + Entity entity = event.getEntity(); + Location location = NukkitUtil.getLocation(entity); + if (!PS.get().hasPlotArea(location.getWorld())) { + return; + } + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + Block from = event.getFrom(); + Block to = event.getTo(); + final Plot finalPlot = area.getOwnedPlotAbs(location); + boolean toBlock = from == null || from.getId() == 0; + if (toBlock) { + List meta = entity.getMetadata("plot"); + if (meta.isEmpty()) { + return; + } + Plot origin = (Plot) meta.get(0).value(); + if (origin != null && !origin.equals(finalPlot)) { + kill(entity, event); + } + } else { + entity.setMetadata("plot", new MetadataValue((Plugin) PS.get().IMP) { + private Plot plot = finalPlot; + @Override + public Object value() { + return plot; + } + @Override + public void invalidate() { + plot = null; + } + }); + } + } + + public static boolean checkEntity(Plot plot, IntegerFlag... flags) { + if (Settings.Done.RESTRICT_BUILDING && Flags.DONE.isSet(plot)) { + return true; + } + int[] mobs = null; + for (IntegerFlag flag : flags) { + int i; + switch (flag.getName()) { + case "entity-cap": + i = 0; + break; + case "mob-cap": + i = 3; + break; + case "hostile-cap": + i = 2; + break; + case "animal-cap": + i = 1; + break; + case "vehicle-cap": + i = 4; + break; + case "misc-cap": + i = 5; + break; + default: + i = 0; + } + int cap = plot.getFlag(flag, Integer.MAX_VALUE); + if (cap == Integer.MAX_VALUE) { + continue; + } + if (cap == 0) { + return true; + } + if (mobs == null) { + mobs = plot.countEntities(); + } + if (mobs[i] >= cap) { + plot.setMeta("EntityCount", mobs); + plot.setMeta("EntityCountTime", System.currentTimeMillis()); + return true; + } + } + if (mobs != null) { + for (IntegerFlag flag : flags) { + int i; + switch (flag.getName()) { + case "entity-cap": + i = 0; + break; + case "mob-cap": + i = 3; + break; + case "hostile-cap": + i = 2; + break; + case "animal-cap": + i = 1; + break; + case "vehicle-cap": + i = 4; + break; + case "misc-cap": + i = 5; + break; + default: + i = 0; + } + mobs[i]++; + } + plot.setMeta("EntityCount", mobs); + plot.setMeta("EntityCountTime", System.currentTimeMillis()); + } + return false; + } + + public static boolean checkEntity(Entity entity, Plot plot) { + if (plot == null || !plot.hasOwner() || plot.getFlags().isEmpty() && plot.getArea().DEFAULT_FLAGS.isEmpty()) { + return false; + } + if (entity instanceof EntityLiving) { + if (entity instanceof EntityCreature) { + if (entity instanceof EntityAnimal || entity instanceof EntityWaterAnimal) { + return checkEntity(plot, Flags.ENTITY_CAP, Flags.MOB_CAP, Flags.ANIMAL_CAP); + } else if (entity instanceof EntityMob) { + return checkEntity(plot, Flags.ENTITY_CAP, Flags.MOB_CAP, Flags.HOSTILE_CAP); + } else if (entity instanceof EntityHuman){ + return false; + } else { + return checkEntity(plot, Flags.ENTITY_CAP, Flags.MOB_CAP, Flags.MOB_CAP); + } + } else { + return checkEntity(plot, Flags.ENTITY_CAP, Flags.MOB_CAP); + } + } else if (entity instanceof EntityVehicle) { + return checkEntity(plot, Flags.ENTITY_CAP, Flags.VEHICLE_CAP); + } else if (entity instanceof EntityHanging){ + return checkEntity(plot, Flags.ENTITY_CAP, Flags.MISC_CAP); + } else { + return checkEntity(plot, Flags.ENTITY_CAP); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockBurn(BlockBurnEvent event) { + Block b = event.getBlock(); + Location location = NukkitUtil.getLocation(b.getLocation()); + + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + + Plot plot = location.getOwnedPlot(); + if (plot == null || !plot.getFlag(Flags.BLOCK_BURN, false)) { + event.setCancelled(true); + return; + } + + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBucketEmpty(PlayerBucketEmptyEvent event) { + Block block = event.getBlockClicked(); + Block b = block.getSide(event.getBlockFace()); + Location location = NukkitUtil.getLocation(b.getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + PlotPlayer pp = NukkitUtil.getPlayer(event.getPlayer()); + Plot plot = area.getPlotAbs(location); + if (plot == null) { + if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_ROAD)) { + return; + } + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_ROAD); + event.setCancelled(true); + } else if (!plot.hasOwner()) { + if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_UNOWNED)) { + return; + } + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_UNOWNED); + event.setCancelled(true); + } else if (!plot.isAdded(pp.getUUID())) { + if (Flags.USE.contains(plot, PlotBlock.get(event.getBucket().getId(), 0))) { + return; + } + if (Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER)) { + return; + } + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onInventoryClose(InventoryCloseEvent event) { + Player closer = event.getPlayer(); + Player player = (Player) closer; + NukkitUtil.getPlayer(player).deleteMeta("inventory"); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onLeave(PlayerQuitEvent event) { + if (TaskManager.TELEPORT_QUEUE.contains(event.getPlayer().getName())) { + TaskManager.TELEPORT_QUEUE.remove(event.getPlayer().getName()); + } + PlotPlayer pp = NukkitUtil.getPlayer(event.getPlayer()); + pp.unregister(); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBucketFill(PlayerBucketFillEvent event) { + Block b = event.getBlockClicked(); + Location location = NukkitUtil.getLocation(b.getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + Player player = event.getPlayer(); + PlotPlayer plotPlayer = NukkitUtil.getPlayer(player); + Plot plot = area.getPlotAbs(location); + if (plot == null) { + if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_BUILD_ROAD)) { + return; + } + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_ROAD); + event.setCancelled(true); + } else if (!plot.hasOwner()) { + if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_BUILD_UNOWNED)) { + return; + } + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_UNOWNED); + event.setCancelled(true); + } else if (!plot.isAdded(plotPlayer.getUUID())) { + Optional> use = plot.getFlag(Flags.USE); + Block block = event.getBlockClicked(); + if (use.isPresent() && use.get().contains(PlotBlock.get(block.getId(), block.getDamage()))) { + return; + } + if (Permissions.hasPermission(plotPlayer, C.PERMISSION_ADMIN_BUILD_OTHER)) { + return; + } + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPotionSplash(PotionCollideEvent event) { + EntityPotion entity = event.getThrownPotion(); + Location l = NukkitUtil.getLocation(entity); + if (!PS.get().hasPlotArea(l.getWorld())) { + return; + } + Entity shooter = entity.shootingEntity; + if (shooter instanceof Player) { + PlotPlayer pp = NukkitUtil.getPlayer((Player) shooter); + Plot plot = l.getOwnedPlotAbs(); + if (plot == null) { + if (!Permissions.hasPermission(pp, C.PERMISSION_PROJECTILE_UNOWNED)) { + kill(entity, event); + return; + } + return; + } + if (plot.isAdded(pp.getUUID()) || Permissions.hasPermission(pp, C.PERMISSION_PROJECTILE_OTHER)) { + return; + } + kill(entity, event); + return; + } + if (shooter == null) { + kill(entity, event); + return; + } + } + + public boolean entityDamage(Entity damager, Entity victim) { + Location dloc = NukkitUtil.getLocation(damager); + Location vloc = NukkitUtil.getLocation(victim); + PlotArea dArea = dloc.getPlotArea(); + PlotArea vArea = dArea != null && dArea.contains(vloc.getX(), vloc.getZ()) ? dArea : vloc.getPlotArea(); + if (dArea == null && vArea == null) { + return true; + } + + Plot dplot = dArea != null ? dArea.getPlot(dloc) : null; + Plot vplot = vArea != null ? vArea.getPlot(vloc) : null; + + Plot plot; + String stub; + if (dplot == null && vplot == null) { + if (dArea == null) { + return true; + } + plot = null; + stub = "road"; + } else { + // Prioritize plots for close to seamless pvp zones + if (victim.ticksLived > damager.ticksLived) { + if (dplot == null || !(victim instanceof Player)) { + if (vplot == null) { + plot = dplot; + } else { + plot = vplot; + } + } else { + plot = dplot; + } + } else if (dplot == null || !(victim instanceof Player)) { + if (vplot == null) { + plot = dplot; + } else { + plot = vplot; + } + } else if (vplot == null) { + plot = dplot; + } else { + plot = vplot; + } + if (plot.hasOwner()) { + stub = "other"; + } else { + stub = "unowned"; + } + } + + Player player; + if (damager instanceof Player) { // attacker is player + player = (Player) damager; + } else if (damager instanceof EntityProjectile) { + EntityProjectile projectile = (EntityProjectile) damager; + Entity shooter = projectile.shootingEntity; + if (shooter instanceof Player) { // shooter is player + player = (Player) shooter; + } else { // shooter is not player + player = null; + } + } else { // Attacker is not player + player = null; + } + if (player != null) { + PlotPlayer plotPlayer = NukkitUtil.getPlayer(player); + if (victim instanceof EntityHanging) { // hanging + if (plot != null && (plot.getFlag(Flags.HANGING_BREAK, false) || plot.isAdded(plotPlayer.getUUID()))) { + return true; + } + if (!Permissions.hasPermission(plotPlayer, "plots.admin.destroy." + stub)) { + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.destroy." + stub); + return false; + } + } else if (false) { // TODO armor stand + if (plot != null && (plot.getFlag(Flags.MISC_BREAK, false) || plot.isAdded(plotPlayer.getUUID()))) { + return true; + } + if (!Permissions.hasPermission(plotPlayer, "plots.admin.destroy." + stub)) { + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.destroy." + stub); + return false; + } + } else if (victim instanceof EntityMob) { // victim is monster + if (plot != null && (plot.getFlag(Flags.HOSTILE_ATTACK, false) || plot.getFlag(Flags.PVE, false) || plot + .isAdded(plotPlayer.getUUID()))) { + return true; + } + if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.pve." + stub); + return false; + } + } else if (false) { // TODO victim is tameable + if (plot != null && (plot.getFlag(Flags.TAMED_ATTACK, false) || plot.getFlag(Flags.PVE, false) || plot.isAdded(plotPlayer.getUUID()))) { + return true; + } + if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.pve." + stub); + return false; + } + } else if (victim instanceof Player) { + if (plot != null) { + if (Flags.PVP.isFalse(plot) && !Permissions.hasPermission(plotPlayer, "plots.admin.pvp." + stub)) { + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.pvp." + stub); + return false; + } else { + return true; + } + } + if (!Permissions.hasPermission(plotPlayer, "plots.admin.pvp." + stub)) { + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.pvp." + stub); + return false; + } + } else if (victim instanceof EntityCreature) { // victim is animal + if (plot != null && (plot.getFlag(Flags.ANIMAL_ATTACK, false) || plot.getFlag(Flags.PVE, false) || plot + .isAdded(plotPlayer.getUUID()))) { + return true; + } + if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.pve." + stub); + return false; + } + } else if (victim instanceof EntityVehicle) { // Vehicles are managed in vehicle destroy event + return true; + } else { // victim is something else + if (plot != null && (plot.getFlag(Flags.PVE, false) || plot.isAdded(plotPlayer.getUUID()))) { + return true; + } + if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { + MainUtil.sendMessage(plotPlayer, C.NO_PERMISSION_EVENT, "plots.admin.pve." + stub); + return false; + } + } + return true; + } + // player is null + return !(damager instanceof EntityProjectile && !(victim instanceof EntityCreature)); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void blockCreate(BlockPlaceEvent event) { + Location location = NukkitUtil.getLocation(event.getBlock().getLocation()); + PlotArea area = location.getPlotArea(); + if (area == null) { + return; + } + Player player = event.getPlayer(); + PlotPlayer pp = NukkitUtil.getPlayer(player); + Plot plot = area.getPlotAbs(location); + if (plot != null) { + if (!plot.hasOwner()) { + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_UNOWNED)) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_UNOWNED); + event.setCancelled(true); + return; + } + } else if (!plot.isAdded(pp.getUUID())) { + Set place = plot.getFlag(Flags.PLACE, null); + if (place != null) { + Block block = event.getBlock(); + if (place.contains(PlotBlock.get((short) block.getId(), block.getDamage()))) { + return; + } + } + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER)) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); + event.setCancelled(true); + return; + } + } else if (Settings.Done.RESTRICT_BUILDING && plot.getFlags().containsKey(Flags.DONE)) { + if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER)) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_OTHER); + event.setCancelled(true); + return; + } + } + if (location.getY() > area.MAX_BUILD_HEIGHT && location.getY() < area.MIN_BUILD_HEIGHT && !Permissions + .hasPermission(pp, C.PERMISSION_ADMIN_BUILD_HEIGHTLIMIT)) { + event.setCancelled(true); + MainUtil.sendMessage(pp, C.HEIGHT_LIMIT.s().replace("{limit}", String.valueOf(area.MAX_BUILD_HEIGHT))); + } + } else if (!Permissions.hasPermission(pp, C.PERMISSION_ADMIN_BUILD_OTHER)) { + MainUtil.sendMessage(pp, C.NO_PERMISSION_EVENT, C.PERMISSION_ADMIN_BUILD_ROAD); + event.setCancelled(true); + } + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/listeners/WorldEvents.java b/Nukkit/src/main/java/com/plotsquared/nukkit/listeners/WorldEvents.java new file mode 100644 index 000000000..36586b4cf --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/listeners/WorldEvents.java @@ -0,0 +1,59 @@ +package com.plotsquared.nukkit.listeners; + +import cn.nukkit.event.EventHandler; +import cn.nukkit.event.EventPriority; +import cn.nukkit.event.Listener; +import cn.nukkit.event.level.LevelInitEvent; +import cn.nukkit.event.level.LevelLoadEvent; +import cn.nukkit.level.Level; +import cn.nukkit.level.generator.Generator; +import com.intellectualcrafters.plot.PS; +import com.intellectualcrafters.plot.generator.GeneratorWrapper; +import com.intellectualcrafters.plot.object.PlotArea; +import com.plotsquared.nukkit.generator.NukkitPlotGenerator; +import java.lang.reflect.Field; +import java.util.HashMap; + +public class WorldEvents implements Listener { + + private final Field instance; + + public WorldEvents() { + try { + this.instance = Level.class.getDeclaredField("generatorInstance"); + this.instance.setAccessible(true); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onWorldLoad(LevelLoadEvent event) { + handle(event.getLevel()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onWorldInit(LevelInitEvent event) { + handle(event.getLevel()); + } + + private void handle(Level level) { + String name = level.getName(); + try { + Generator gen = (Generator) instance.get(level); + if (gen instanceof GeneratorWrapper) { + PS.get().loadWorld(name, (GeneratorWrapper) gen); + } else { + HashMap settings = new HashMap<>(); + settings.put("world", level.getName()); + settings.put("generator", gen); + PS.get().loadWorld(name, new NukkitPlotGenerator(settings)); + for (PlotArea area : PS.get().getPlotAreas(name)) { + area.MAX_BUILD_HEIGHT = Math.min(128, area.MAX_BUILD_HEIGHT); + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/object/NukkitPlayer.java b/Nukkit/src/main/java/com/plotsquared/nukkit/object/NukkitPlayer.java new file mode 100644 index 000000000..db55bb322 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/object/NukkitPlayer.java @@ -0,0 +1,215 @@ +package com.plotsquared.nukkit.object; + +import cn.nukkit.Player; +import cn.nukkit.event.player.PlayerTeleportEvent; +import cn.nukkit.plugin.RegisteredListener; +import cn.nukkit.utils.EventException; +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.StringMan; +import com.intellectualcrafters.plot.util.UUIDHandler; +import com.plotsquared.nukkit.util.NukkitUtil; +import java.util.UUID; + +public class NukkitPlayer extends PlotPlayer { + + public final Player player; + public boolean offline; + private UUID uuid; + private String name; + + /** + *

Please do not use this method. Instead use + * NukkitUtil.getPlayer(Player), as it caches player objects.

+ * @param player + */ + public NukkitPlayer(Player player) { + this.player = player; + super.populatePersistentMetaMap(); + } + + public NukkitPlayer(Player player, boolean offline) { + this.player = player; + this.offline = offline; + super.populatePersistentMetaMap(); + } + + @Override + public Location getLocation() { + Location location = super.getLocation(); + return location == null ? NukkitUtil.getLocation(this.player) : location; + } + + @Override + public UUID getUUID() { + if (this.uuid == null) { + this.uuid = UUIDHandler.getUUID(this); + } + return this.uuid; + } + + @Override public long getLastPlayed() { + return this.player.getLastPlayed(); + } + + @Override + public boolean canTeleport(Location loc) { + cn.nukkit.level.Location to = NukkitUtil.getLocation(loc); + cn.nukkit.level.Location from = player.getLocation(); + PlayerTeleportEvent event = new PlayerTeleportEvent(player, from, to, PlayerTeleportEvent.TeleportCause.PLUGIN); + RegisteredListener[] listeners = event.getHandlers().getRegisteredListeners(); + for (RegisteredListener listener : listeners) { + if (listener.getPlugin().getName().equals("PlotSquared")) { + continue; + } + try { + listener.callEvent(event); + } catch (EventException e) { + e.printStackTrace(); + } + } + if (event.isCancelled() || !event.getTo().equals(to)) { + return false; + } + event = new PlayerTeleportEvent(player, to, from, PlayerTeleportEvent.TeleportCause.PLUGIN); + for (RegisteredListener listener : listeners) { + if (listener.getPlugin().getName().equals("PlotSquared")) { + continue; + } + try { + listener.callEvent(event); + } catch (EventException e) { + e.printStackTrace(); + } + } + return true; + } + + @Override + public boolean hasPermission(String permission) { + if (this.offline && EconHandler.manager != null) { + return EconHandler.manager.hasPermission(getName(), permission); + } + return this.player.hasPermission(permission); + } + + @Override + public void sendMessage(String message) { + if (!StringMan.isEqual(this.getMeta("lastMessage"), message) || (System.currentTimeMillis() - this.getMeta("lastMessageTime") > 5000)) { + setMeta("lastMessage", message); + setMeta("lastMessageTime", System.currentTimeMillis()); + this.player.sendMessage(message); + } + } + + @Override + public void teleport(Location to) { + if (Math.abs(to.getX()) >= 30000000 || Math.abs(to.getZ()) >= 30000000) { + return; + } + cn.nukkit.level.Location loc = new cn.nukkit.level.Location(to.getX() + 0.5, to.getY(), to.getZ() + 0.5, to.getYaw(), to.getPitch(), NukkitUtil.getWorld(to.getWorld())); + this.player.teleport(loc); + } + + @Override + public String getName() { + if (this.name == null) { + this.name = this.player.getName(); + } + return this.name; + } + + @Override + public boolean isOnline() { + return !this.offline && this.player.isOnline(); + } + + @Override + public void setCompassTarget(Location location) { + throw new UnsupportedOperationException("Not implemented yet: setCompassTarget"); + } + + @Override + public Location getLocationFull() { + return NukkitUtil.getLocationFull(this.player); + } + + @Override + public void setWeather(PlotWeather weather) { + throw new UnsupportedOperationException("Not implemented yet: setWeather"); + } + + @Override + public PlotGameMode getGameMode() { + switch (this.player.getGamemode()) { + case 0: + return PlotGameMode.SURVIVAL; + case 1: + return PlotGameMode.CREATIVE; + case 2: + return PlotGameMode.ADVENTURE; + case 3: + return PlotGameMode.SPECTATOR; + default: + return PlotGameMode.NOT_SET; + } + } + + @Override + public void setGameMode(PlotGameMode gameMode) { + switch (gameMode) { + case ADVENTURE: + this.player.setGamemode(2); + break; + case CREATIVE: + this.player.setGamemode(1); + break; + case SPECTATOR: + this.player.setGamemode(3); + break; + case SURVIVAL: + this.player.setGamemode(0); + break; + default: + this.player.setGamemode(0); + break; + } + } + + @Override + public void setTime(long time) { + throw new UnsupportedOperationException("Not implemented yet: setTIme"); + } + + @Override + public void setFlight(boolean fly) { + this.player.setAllowFlight(fly); + } + + @Override + public boolean getFlight() { + return player.getAllowFlight(); + } + + @Override + public void playMusic(Location location, int id) { + throw new UnsupportedOperationException("Not implemented yet: playMusic"); + } + + @Override + public void kick(String message) { + player.kick(message); + } + + @Override public void stopSpectating() { + // Do nothing + } + + @Override + public boolean isBanned() { + return this.player.isBanned(); + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/util/Metrics.java b/Nukkit/src/main/java/com/plotsquared/nukkit/util/Metrics.java new file mode 100644 index 000000000..eb88fa3d1 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/util/Metrics.java @@ -0,0 +1,579 @@ +package com.plotsquared.nukkit.util; + +import cn.nukkit.plugin.Plugin; +import cn.nukkit.plugin.PluginDescription; +import cn.nukkit.utils.LogLevel; +import com.intellectualcrafters.plot.PS; +import com.intellectualcrafters.plot.util.TaskManager; +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.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.UUID; +import java.util.zip.GZIPOutputStream; + +public class Metrics { + + /** + * The current revision number. + */ + private static final 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 graphs = Collections.synchronizedSet(new HashSet()); + /** + * Unique server id. + */ + private final String guid; + /** + * Debug mode. + */ + private final boolean debug; + /** + * The scheduled task. + */ + private volatile int taskId = -1; + + public Metrics(Plugin plugin) { + if (plugin == null) { + throw new IllegalArgumentException("Plugin cannot be null"); + } + this.plugin = plugin; + this.guid = UUID.randomUUID().toString(); + this.debug = false; + } + + /** + * GZip compress a string of bytes. + * + * @param input + * + * @return byte[] the file as a byte array + */ + public static byte[] gzip(String input) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + GZIPOutputStream gzos = null; + try { + gzos = new GZIPOutputStream(baos); + gzos.write(input.getBytes("UTF-8")); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (gzos != null) { + try { + gzos.close(); + } catch (IOException ignore) { + } + } + } + return baos.toByteArray(); + } + + /** + * Appends a json encoded key/value pair to the given string builder. + * + * @param json + * @param key + * @param value + * + */ + private static void appendJSONPair(StringBuilder json, String key, String value) { + boolean isValueNumeric = false; + try { + if (value.equals("0") || !value.endsWith("0")) { + Double.parseDouble(value); + isValueNumeric = true; + } + } catch (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(String text) { + StringBuilder builder = new StringBuilder(); + builder.append('"'); + for (int index = 0; index < text.length(); index++) { + 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 < ' ') { + 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(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(String name) { + if (name == null) { + throw new IllegalArgumentException("Graph name cannot be null"); + } + // Construct the graph object + Graph graph = new Graph(name); + // Now we can add our graph + this.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(Graph graph) { + if (graph == null) { + throw new IllegalArgumentException("Graph cannot be null"); + } + this.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() { + // Is metrics already running? + if (this.taskId != -1) { + return true; + } + // Begin hitting the server with glorious data + this.taskId = TaskManager.IMP.taskRepeatAsync(new Runnable() { + private boolean firstPost = true; + @Override + public void run() { + try { + postPlugin(!this.firstPost); + // After the first post we set firstPost to + // false + // Each post thereafter will be a ping + this.firstPost = false; + } catch (IOException e) { + e.printStackTrace(); + if (Metrics.this.debug) { + plugin.getLogger().log(LogLevel.INFO, "[Metrics] " + e.getMessage()); + } + } + } + }, PING_INTERVAL * 1200); + return true; + } + + /** + * 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() { + // Enable Task, if it is not running + if (this.taskId == -1) { + start(); + } + } + + /** + * Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task. + * + */ + public void disable() { + // Disable Task, if it is running + if (this.taskId != -1) { + TaskManager.IMP.cancelTask(this.taskId); + this.taskId = -1; + } + } + + /** + * 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. + File pluginsFolder = this.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(boolean isPing) throws IOException { + // Server software specific section + PluginDescription description = this.plugin.getDescription(); + String pluginName = description.getName(); + boolean onlineMode = false; + String pluginVersion = description.getVersion(); + String serverVersion = plugin.getServer().getNukkitVersion(); + int playersOnline = plugin.getServer().getOnlinePlayers().size(); + // END server software specific section -- all code below does not use + // any code outside of this class / Java + // Construct the post data + StringBuilder json = new StringBuilder(1024); + json.append('{'); + // The plugin's description file containing all of the plugin data such as name, version, author, etc + appendJSONPair(json, "guid", this.guid); + appendJSONPair(json, "plugin_version", pluginVersion); + appendJSONPair(json, "server_version", serverVersion); + appendJSONPair(json, "players_online", Integer.toString(playersOnline)); + // New data as of R6 + String osname = System.getProperty("os.name"); + String osarch = System.getProperty("os.arch"); + String osversion = System.getProperty("os.version"); + String java_version = System.getProperty("java.version"); + 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 (!this.graphs.isEmpty()) { + synchronized (this.graphs) { + json.append(','); + json.append('"'); + json.append("graphs"); + json.append('"'); + json.append(':'); + json.append('{'); + boolean firstGraph = true; + for (Graph graph : this.graphs) { + StringBuilder graphJson = new StringBuilder(); + graphJson.append('{'); + for (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 + 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(); + } + byte[] uncompressed = json.toString().getBytes(); + 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 (this.debug) { + PS.debug("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length); + } + try { + try (OutputStream os = connection.getOutputStream()) { + os.write(compressed); + os.flush(); + } + String response; + try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { + response = reader.readLine(); + if (this.debug) { + PS.debug("[Metrics] Response for " + pluginName + ": " + response); + } + } + 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 (this.graphs) { + for (Graph graph : this.graphs) { + for (Plotter plotter : graph.getPlotters()) { + plotter.reset(); + } + } + } + } + } + } catch (Exception e) { + if (this.debug) { + e.printStackTrace(); + } + } + } + + /** + * 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 plotters = new LinkedHashSet<>(); + + private Graph(String name) { + this.name = name; + } + + /** + * Gets the graph's name + * + * @return the Graph's name + */ + public String getName() { + return this.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(Plotter plotter) { + this.plotters.add(plotter); + } + + /** + * Remove a plotter from the graph + * + * @param plotter the plotter to remove from the graph + */ + public void removePlotter(Plotter plotter) { + this.plotters.remove(plotter); + } + + /** + * Gets an unmodifiable set of the plotter objects in the graph + * + * @return an unmodifiable {@link java.util.Set} of the plotter objects + */ + public Set getPlotters() { + return Collections.unmodifiableSet(this.plotters); + } + + @Override + public int hashCode() { + return this.name.hashCode(); + } + + @Override + public boolean equals(Object object) { + if (!(object instanceof Graph)) { + return false; + } + Graph graph = (Graph) object; + return graph.name.equals(this.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 abstract static 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(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 this.name; + } + + /** + * Called after the website graphs have been updated + */ + public void reset() { + } + + @Override + public int hashCode() { + return getColumnName().hashCode(); + } + + @Override + public boolean equals(Object object) { + if (!(object instanceof Plotter)) { + return false; + } + Plotter plotter = (Plotter) object; + return plotter.name.equals(this.name) && plotter.getValue() == getValue(); + } + } +} \ No newline at end of file diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitChunkManager.java b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitChunkManager.java new file mode 100644 index 000000000..295b62697 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitChunkManager.java @@ -0,0 +1,49 @@ +package com.plotsquared.nukkit.util; + + +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.util.ChunkManager; + +public class NukkitChunkManager extends ChunkManager { + public NukkitChunkManager() { + PS.debug("Not implemented: NukkitChunkManager"); + } + + @Override + public int[] countEntities(Plot plot) { + return new int[0]; + } + + @Override + public boolean loadChunk(String world, ChunkLoc loc, boolean force) { + return false; + } + + @Override + public void unloadChunk(String world, ChunkLoc loc, boolean save, boolean safe) { + + } + + @Override + public boolean copyRegion(Location pos1, Location pos2, Location newPos, Runnable whenDone) { + return false; + } + + @Override + public boolean regenerateRegion(Location pos1, Location pos2, boolean ignoreAugment, Runnable whenDone) { + return false; + } + + @Override + public void clearAllEntities(Location pos1, Location pos2) { + + } + + @Override + public void swap(Location bot1, Location top1, Location bot2, Location top2, Runnable whenDone) { + whenDone.run(); + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitCommand.java b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitCommand.java new file mode 100644 index 000000000..5805daf6a --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitCommand.java @@ -0,0 +1,28 @@ +package com.plotsquared.nukkit.util; + +import cn.nukkit.Player; +import cn.nukkit.command.Command; +import cn.nukkit.command.CommandSender; +import cn.nukkit.command.ConsoleCommandSender; +import cn.nukkit.command.RemoteConsoleCommandSender; +import com.intellectualcrafters.plot.commands.MainCommand; +import com.intellectualcrafters.plot.object.ConsolePlayer; + +public class NukkitCommand extends Command { + + public NukkitCommand(String cmd, String[] aliases) { + super(cmd, "PlotSquared command", "/plot", aliases); + } + + + @Override + public boolean execute(CommandSender commandSender, String commandLabel, String[] args) { + if (commandSender instanceof Player) { + return MainCommand.onCommand(NukkitUtil.getPlayer((Player) commandSender), args); + } + if (commandSender instanceof ConsoleCommandSender || commandSender instanceof RemoteConsoleCommandSender) { + return MainCommand.onCommand(ConsolePlayer.getConsole(), args); + } + return false; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitEventUtil.java b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitEventUtil.java new file mode 100644 index 000000000..24b1bbd5a --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitEventUtil.java @@ -0,0 +1,138 @@ +package com.plotsquared.nukkit.util; + +import cn.nukkit.Player; +import cn.nukkit.event.Cancellable; +import cn.nukkit.event.Event; +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.nukkit.NukkitMain; +import com.plotsquared.nukkit.events.ClusterFlagRemoveEvent; +import com.plotsquared.nukkit.events.PlayerClaimPlotEvent; +import com.plotsquared.nukkit.events.PlayerEnterPlotEvent; +import com.plotsquared.nukkit.events.PlayerLeavePlotEvent; +import com.plotsquared.nukkit.events.PlayerPlotDeniedEvent; +import com.plotsquared.nukkit.events.PlayerPlotHelperEvent; +import com.plotsquared.nukkit.events.PlayerPlotTrustedEvent; +import com.plotsquared.nukkit.events.PlayerTeleportToPlotEvent; +import com.plotsquared.nukkit.events.PlotClearEvent; +import com.plotsquared.nukkit.events.PlotComponentSetEvent; +import com.plotsquared.nukkit.events.PlotDeleteEvent; +import com.plotsquared.nukkit.events.PlotFlagAddEvent; +import com.plotsquared.nukkit.events.PlotFlagRemoveEvent; +import com.plotsquared.nukkit.events.PlotMergeEvent; +import com.plotsquared.nukkit.events.PlotRateEvent; +import com.plotsquared.nukkit.events.PlotUnlinkEvent; +import com.plotsquared.nukkit.object.NukkitPlayer; +import java.util.ArrayList; +import java.util.UUID; + +public class NukkitEventUtil extends EventUtil { + + private final NukkitMain plugin; + + public NukkitEventUtil(NukkitMain plugin) { + this.plugin = plugin; + } + + public Player getPlayer(PlotPlayer player) { + if (player instanceof NukkitPlayer) { + return ((NukkitPlayer) player).player; + } + return null; + } + + public boolean callEvent(Event event) { + plugin.getServer().getPluginManager().callEvent(event); + return !(event instanceof Cancellable) || !((Cancellable) event).isCancelled(); + } + + @Override + public boolean callClaim(PlotPlayer player, Plot plot, boolean auto) { + return callEvent(new PlayerClaimPlotEvent(getPlayer(player), plot, auto)); + } + + @Override + public boolean callTeleport(PlotPlayer player, Location from, Plot plot) { + return callEvent(new PlayerTeleportToPlotEvent(getPlayer(player), from, plot)); + } + + @Override + public boolean callComponentSet(Plot plot, String component) { + return callEvent(new PlotComponentSetEvent(plot, component)); + } + + @Override + public boolean callClear(Plot plot) { + return callEvent(new PlotClearEvent(plot)); + } + + @Override + public void callDelete(Plot plot) { + callEvent(new PlotDeleteEvent(plot)); + } + + @Override + public boolean callFlagAdd(Flag flag, Plot plot) { + return callEvent(new PlotFlagAddEvent(flag, plot)); + } + + @Override + public boolean callFlagRemove(Flag flag, Plot plot, Object value) { + return callEvent(new PlotFlagRemoveEvent(flag, plot)); + } + + @Override + public boolean callMerge(Plot plot, ArrayList plots) { + return callEvent(new PlotMergeEvent(NukkitUtil.getWorld(plot.getArea().worldname), plot, plots)); + } + + @Override + public boolean callUnlink(PlotArea area, ArrayList plots) { + return callEvent(new PlotUnlinkEvent(NukkitUtil.getWorld(area.worldname), area, plots)); + } + + @Override + public void callEntry(PlotPlayer player, Plot plot) { + callEvent(new PlayerEnterPlotEvent(getPlayer(player), plot)); + } + + @Override + public void callLeave(PlotPlayer player, Plot plot) { + callEvent(new PlayerLeavePlotEvent(getPlayer(player), plot)); + } + + @Override + public void callDenied(PlotPlayer initiator, Plot plot, UUID player, boolean added) { + callEvent(new PlayerPlotDeniedEvent(getPlayer(initiator), plot, player, added)); + } + + @Override + public void callTrusted(PlotPlayer initiator, Plot plot, UUID player, boolean added) { + callEvent(new PlayerPlotTrustedEvent(getPlayer(initiator), plot, player, added)); + } + + @Override + public void callMember(PlotPlayer initiator, Plot plot, UUID player, boolean added) { + callEvent(new PlayerPlotHelperEvent(getPlayer(initiator), plot, player, added)); + } + + @Override + public boolean callFlagRemove(Flag flag, Object object, PlotCluster cluster) { + return callEvent(new ClusterFlagRemoveEvent(flag, cluster)); + } + + @Override + public Rating callRating(PlotPlayer player, Plot plot, Rating rating) { + PlotRateEvent event = new PlotRateEvent(player, rating, plot); + plugin.getServer().getPluginManager().callEvent(event); + return event.getRating(); + } + +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitHybridUtils.java b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitHybridUtils.java new file mode 100644 index 000000000..2436b67d7 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitHybridUtils.java @@ -0,0 +1,19 @@ +package com.plotsquared.nukkit.util; + +import com.intellectualcrafters.plot.PS; +import com.intellectualcrafters.plot.generator.HybridUtils; +import com.intellectualcrafters.plot.object.RegionWrapper; +import com.intellectualcrafters.plot.object.RunnableVal; +import com.intellectualcrafters.plot.util.expiry.PlotAnalysis; + +public class NukkitHybridUtils extends HybridUtils { + + public NukkitHybridUtils() { + PS.debug("Not implemented: NukkitHybridUtils"); + } + + @Override + public void analyzeRegion(final String world, final RegionWrapper region, final RunnableVal whenDone) { + throw new UnsupportedOperationException("NOT IMPLEMENTED YET"); + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitInventoryUtil.java b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitInventoryUtil.java new file mode 100644 index 000000000..741dc2014 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitInventoryUtil.java @@ -0,0 +1,77 @@ +package com.plotsquared.nukkit.util; + +import cn.nukkit.inventory.PlayerInventory; +import cn.nukkit.item.Item; +import com.intellectualcrafters.plot.PS; +import com.intellectualcrafters.plot.config.C; +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.nukkit.object.NukkitPlayer; + +public class NukkitInventoryUtil extends InventoryUtil { + + public NukkitInventoryUtil() { + PS.debug("Not implemented: NukkitInventoryUtil"); + } + + public static Item getItem(PlotItemStack item) { + if (item == null) { + return null; + } + Item stack = new Item(item.id, item.amount, item.data); + if (item.name != null) { + stack.setCustomName(C.color(item.name)); + } + if (item.lore != null) { + // TODO not implemented + } + return stack; + } + + @Override + public void open(PlotInventory inv) { + return; // TODO + } + + @Override + public void close(PlotInventory inv) { + return; // TODO + } + + @Override + public void setItem(PlotInventory inv, int index, PlotItemStack item) { + return; // TODO + } + + public PlotItemStack getItem(Item item) { + if (item == null) { + return null; + } + int id = item.getId(); + int data = item.getDamage(); + int amount = item.count; + String name = item.getCustomName(); + if (name.length() == 0) { + name = null; + } + return new PlotItemStack(id, (short) data, amount, name); + } + + @Override + public PlotItemStack[] getItems(PlotPlayer player) { + NukkitPlayer bp = (NukkitPlayer) player; + PlayerInventory inv = bp.player.getInventory(); + PlotItemStack[] items = new PlotItemStack[36]; + for (int i = 0; i < 36; i++) { + items[i] = getItem(inv.getItem(i)); + } + return items; + } + + @Override + public boolean isOpen(PlotInventory inv) { + return false; // TODO + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitSchematicHandler.java b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitSchematicHandler.java new file mode 100644 index 000000000..f8b2aec6a --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitSchematicHandler.java @@ -0,0 +1,186 @@ +package com.plotsquared.nukkit.util; + +import cn.nukkit.block.Block; +import cn.nukkit.level.Level; +import cn.nukkit.level.format.generic.BaseFullChunk; +import cn.nukkit.math.Vector3; +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.intellectualcrafters.plot.util.block.LocalBlockQueue; +import com.plotsquared.nukkit.NukkitMain; +import java.io.IOException; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Set; + +/** + * Schematic Handler. + */ +public class NukkitSchematicHandler extends SchematicHandler { + + private final NukkitMain plugin; + + public NukkitSchematicHandler(NukkitMain plugin) { + this.plugin = plugin; + } + + @Override + public void getCompoundTag(final String world, final Set regions, final RunnableVal whenDone) { + // async + TaskManager.runTaskAsync(new Runnable() { + @Override + public void run() { + // Main positions + Location[] corners = MainUtil.getCorners(world, regions); + final Location bot = corners[0]; + Location top = corners[1]; + + final int width = top.getX() - bot.getX() + 1; + int height = top.getY() - bot.getY() + 1; + final int length = top.getZ() - bot.getZ() + 1; + // Main Schematic tag + final HashMap 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 tileEntities = new ArrayList<>(); + final byte[] blocks = new byte[width * height * length]; + final byte[] blockData = new byte[width * height * length]; + // Queue + final ArrayDeque 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())); + 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 chunks = new ArrayList<>(); + for (int x = bcx; x <= tcx; x++) { + for (int z = bcz; z <= tcz; z++) { + chunks.add(new ChunkLoc(x, z)); + } + } + final Level worldObj = plugin.getServer().getLevelByName(world); + // Main thread + final Vector3 mutable = new Vector3(); + TaskManager.runTask(new Runnable() { + @Override + public void run() { + long start = System.currentTimeMillis(); + while (!chunks.isEmpty() && System.currentTimeMillis() - start < 20) { + // save schematics + ChunkLoc chunk = chunks.remove(0); + BaseFullChunk bc = worldObj.getChunk(chunk.x, chunk.z); + try { + bc.load(false); + } catch (IOException e) { + continue; + } + int X = chunk.x; + 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++) { + int ry = y - sy; + int i1 = ry * width * length; + for (int z = zzb; z <= zzt; z++) { + int rz = z - bz; + int i2 = i1 + rz * width; + for (int x = xxb; x <= xxt; x++) { + int rx = x - bx; + int index = i2 + rx; + mutable.x = x; + mutable.y = y; + mutable.z = z; + Block block = worldObj.getBlock(mutable); + blocks[index] = (byte) block.getId(); + blockData[index] = (byte) block.getDamage(); + } + } + } + } + if (!chunks.isEmpty()) { + TaskManager.runTaskLater(this, 1); + } else { + regionTask.run(); + } + } + }); + } + }); + } + }); + } + + @Override + public boolean restoreTile(LocalBlockQueue queue, CompoundTag ct, int x, int y, int z) { + return false; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitSetupUtils.java b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitSetupUtils.java new file mode 100644 index 000000000..4e8e999be --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitSetupUtils.java @@ -0,0 +1,169 @@ +package com.plotsquared.nukkit.util; + +import cn.nukkit.level.Level; +import cn.nukkit.level.generator.Generator; +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.generator.HybridGen; +import com.intellectualcrafters.plot.object.PlotArea; +import com.intellectualcrafters.plot.object.SetupObject; +import com.intellectualcrafters.plot.util.SetupUtils; +import com.plotsquared.nukkit.NukkitMain; +import com.plotsquared.nukkit.generator.NukkitPlotGenerator; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map.Entry; +import java.util.Objects; + +public class NukkitSetupUtils extends SetupUtils { + + private final NukkitMain plugin; + + public NukkitSetupUtils(NukkitMain plugin) { + this.plugin = plugin; + } + + @Override + public void updateGenerators() { + if (!SetupUtils.generators.isEmpty()) { + return; + } + String testWorld = "CheckingPlotSquaredGenerator"; + HashMap map = new HashMap(); + map.put("world", testWorld); + map.put("plot-generator", new HybridGen()); + NukkitPlotGenerator gen = new NukkitPlotGenerator(map); + SetupUtils.generators.put("PlotSquared", gen); + } + + @Override + public String setupWorld(SetupObject object) { + SetupUtils.manager.updateGenerators(); + ConfigurationNode[] steps = object.step == null ? new ConfigurationNode[0] : object.step; + String world = object.world; + int type = object.type; + String worldPath = "worlds." + object.world; + if (!PS.get().worlds.contains(worldPath)) { + PS.get().worlds.createSection(worldPath); + } + ConfigurationSection worldSection = PS.get().worlds.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 options = new HashMap<>(); + for (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 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 = SetupUtils.generators.get(object.setupGenerator); + if (gen != null && gen.isFull()) { + object.setupGenerator = null; + } + break; + } + case 1: + for (ConfigurationNode step : steps) { + worldSection.set(step.getConstant(), step.getValue()); + } + PS.get().worlds.set("worlds." + world + ".generator.type", object.type); + PS.get().worlds.set("worlds." + world + ".generator.terrain", object.terrain); + PS.get().worlds.set("worlds." + world + ".generator.plugin", object.plotManager); + if (object.setupGenerator != null && !object.setupGenerator.equals(object.plotManager)) { + PS.get().worlds.set("worlds." + world + ".generator.init", object.setupGenerator); + } + GeneratorWrapper gen = SetupUtils.generators.get(object.setupGenerator); + if (gen != null && gen.isFull()) { + object.setupGenerator = null; + } + break; + case 0: + for (ConfigurationNode step : steps) { + worldSection.set(step.getConstant(), step.getValue()); + } + break; + } + try { + PS.get().worlds.save(PS.get().worldsFile); + } catch (IOException e) { + e.printStackTrace(); + } + if (object.setupGenerator != null) { + HashMap map = new HashMap(); + map.put("world", object.world); + map.put("plot-generator", new HybridGen()); + plugin.getServer().generateLevel(object.world, object.world.hashCode(), NukkitPlotGenerator.class, map); + } else { + plugin.getServer().generateLevel(object.world, object.world.hashCode()); + } + return object.world; + } + + public void setGenerator(String world, String generator) { + File file = new File("nukkit.yml").getAbsoluteFile(); + YamlConfiguration yml = YamlConfiguration.loadConfiguration(file); + yml.set("worlds." + world + ".generator", generator); + try { + yml.save(file); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public String getGenerator(PlotArea plotArea) { + if (SetupUtils.generators.isEmpty()) { + updateGenerators(); + } + Level world = NukkitUtil.getWorld(plotArea.worldname); + if (world == null) { + return null; + } + try { + Field field = Level.class.getDeclaredField("generatorInstance"); + field.setAccessible(true); + Generator generator = (Generator) field.get(world); + if (!(generator instanceof NukkitPlotGenerator)) { + return null; + } + for (Entry> entry : SetupUtils.generators.entrySet()) { + GeneratorWrapper current = entry.getValue(); + if (current.equals(generator)) { + return entry.getKey(); + } + } + return "PlotSquared"; + } catch (Throwable e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitTaskManager.java b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitTaskManager.java new file mode 100644 index 000000000..2fa1a4440 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitTaskManager.java @@ -0,0 +1,68 @@ +package com.plotsquared.nukkit.util; + +import cn.nukkit.scheduler.TaskHandler; +import com.intellectualcrafters.plot.util.TaskManager; +import com.plotsquared.nukkit.NukkitMain; +import java.util.HashMap; +import java.util.concurrent.atomic.AtomicInteger; + +public class NukkitTaskManager extends TaskManager { + + private final NukkitMain plugin; + + public NukkitTaskManager(NukkitMain bukkitMain) { + this.plugin = bukkitMain; + } + + private AtomicInteger index = new AtomicInteger(0); + private HashMap tasks = new HashMap<>(); + + @Override + public int taskRepeat(Runnable r, int interval) { + TaskHandler task = this.plugin.getServer().getScheduler().scheduleRepeatingTask(r, interval, false); + return task.getTaskId(); + } + + @SuppressWarnings("deprecation") + @Override + public int taskRepeatAsync(Runnable r, int interval) { + TaskHandler task = this.plugin.getServer().getScheduler().scheduleRepeatingTask(r, interval, true); + return task.getTaskId(); + } + + @Override + public void taskAsync(Runnable r) { + if (r == null) { + return; + } + this.plugin.getServer().getScheduler().scheduleTask(r, true); + } + + @Override + public void task(Runnable r) { + if (r == null) { + return; + } + this.plugin.getServer().getScheduler().scheduleTask(r, false); + } + + @Override + public void taskLater(Runnable r, int delay) { + if (r == null) { + return; + } + this.plugin.getServer().getScheduler().scheduleDelayedTask(r, delay); + } + + @Override + public void taskLaterAsync(Runnable r, int delay) { + this.plugin.getServer().getScheduler().scheduleDelayedTask(r, delay, true); + } + + @Override + public void cancelTask(int task) { + if (task != -1) { + this.plugin.getServer().getScheduler().cancelTask(task); + } + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitUtil.java b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitUtil.java new file mode 100644 index 000000000..21c635500 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/util/NukkitUtil.java @@ -0,0 +1,292 @@ +package com.plotsquared.nukkit.util; + +import cn.nukkit.OfflinePlayer; +import cn.nukkit.Player; +import cn.nukkit.block.Block; +import cn.nukkit.block.BlockWallSign; +import cn.nukkit.blockentity.BlockEntity; +import cn.nukkit.blockentity.BlockEntitySign; +import cn.nukkit.entity.Entity; +import cn.nukkit.item.Item; +import cn.nukkit.level.Level; +import cn.nukkit.level.Position; +import cn.nukkit.level.generator.biome.Biome; +import cn.nukkit.math.Vector3; +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.UUIDHandler; +import com.intellectualcrafters.plot.util.WorldUtil; +import com.plotsquared.nukkit.NukkitMain; +import com.plotsquared.nukkit.object.NukkitPlayer; +import java.lang.reflect.Field; +import java.util.ArrayList; + +public class NukkitUtil extends WorldUtil { + + private static String lastString = null; + private static Level lastWorld = null; + + private static Player lastPlayer = null; + private static PlotPlayer lastPlotPlayer = null; + private static NukkitMain plugin; + + public NukkitUtil(NukkitMain plugin) { + this.plugin = plugin; + } + + public static void removePlayer(String player) { + lastPlayer = null; + lastPlotPlayer = null; + } + + public static PlotPlayer getPlayer(OfflinePlayer op) { + if (op.isOnline()) { + return getPlayer(op.getPlayer()); + } + return null; + } + + public static PlotPlayer getPlayer(Player player) { + if (player == lastPlayer) { + return lastPlotPlayer; + } + String name = player.getName(); + PlotPlayer plotPlayer = UUIDHandler.getPlayer(name); + if (plotPlayer != null) { + return plotPlayer; + } + lastPlotPlayer = new NukkitPlayer(player); + UUIDHandler.getPlayers().put(name, lastPlotPlayer); + lastPlayer = player; + return lastPlotPlayer; + } + + public static Location getLocation(cn.nukkit.level.Location location) { + return new Location(location.getLevel().getName(), MathMan.roundInt(location.getX()), MathMan.roundInt(location.getY()), + MathMan.roundInt(location.getZ())); + } + + public static Location getLocation(cn.nukkit.level.Position location) { + return new Location(location.getLevel().getName(), MathMan.roundInt(location.getX()), MathMan.roundInt(location.getY()), + MathMan.roundInt(location.getZ())); + } + + public static cn.nukkit.level.Location getLocation(Location location) { + return new cn.nukkit.level.Location(location.getX(), location.getY(), location.getZ(), 0, 0, getWorld(location.getWorld())); + } + + public static Level getWorld(String string) { + if (StringMan.isEqual(string, lastString)) { + if (lastWorld != null) { + return lastWorld; + } + } + Level world = plugin.getServer().getLevelByName(string); + lastString = string; + lastWorld = world; + return world; + } + + public static String getWorld(Entity entity) { + return entity.getLevel().getName(); + } + + public static Entity[] getEntities(String worldName) { + return getWorld(worldName).getEntities(); + } + + public static Location getLocation(Entity entity) { + cn.nukkit.level.Location location = entity.getLocation(); + String world = location.getLevel().getName(); + return new Location(world, location.getFloorX(), location.getFloorY(), location.getFloorZ()); + } + + public static Location getLocationFull(Entity entity) { + cn.nukkit.level.Location location = entity.getLocation(); + return new Location(location.getLevel().getName(), MathMan.roundInt(location.getX()), MathMan.roundInt(location.getY()), MathMan.roundInt(location.getZ()), + (float) location.getYaw(), (float) location.getPitch()); + } + + @Override + public boolean isWorld(String worldName) { + return getWorld(worldName) != null; + } + + @Override + public String getBiome(String world, int x, int z) { + int id = getWorld(world).getBiomeId(x, z); + return Biome.getBiome(id).getName(); + } + + @Override + public void setSign(String worldName, int x, int y, int z, String[] lines) { + Level world = getWorld(worldName); + BlockWallSign sign = new BlockWallSign(0); + Vector3 pos = new Vector3(x, y, z); + world.setBlock(pos, sign); + BlockEntity tile = world.getBlockEntity(pos); + if (tile instanceof BlockEntitySign) { + ((BlockEntitySign) tile).setText(lines[0], lines[1], lines[2], lines[3]); + tile.scheduleUpdate(); + } + } + + @Override + public String[] getSign(Location location) { + Level world = getWorld(location.getWorld()); + Vector3 pos = new Vector3(location.getX(), location.getY(), location.getZ()); + BlockEntity tile = world.getBlockEntity(pos); + if (tile instanceof BlockEntitySign) { + return ((BlockEntitySign) tile).getText(); + } + return null; + } + + @Override + public Location getSpawn(PlotPlayer player) { + return getLocation(((NukkitPlayer) player).player.getSpawn()); + } + + @Override + public Location getSpawn(String world) { + Position loc = getWorld(world).getSpawnLocation(); + return new Location(world, loc.getFloorX(), loc.getFloorY(), loc.getFloorZ(), 0, 0); + } + + @Override + public void setSpawn(Location location) { + Level world = getWorld(location.getWorld()); + if (world != null) { + world.setSpawnLocation(new Vector3(location.getX(), location.getY(), location.getZ())); + } + } + + @Override + public void saveWorld(String worldName) { + Level world = getWorld(worldName); + if (world != null) { + world.save(); + } + } + + @Override + public int getHighestBlock(String world, int x, int z) { + return getWorld(world).getHeightMap(x, z); + } + + @Override + public int getBiomeFromString(String biomeString) { + try { + Biome biome = Biome.getBiome(biomeString.toUpperCase()); + return biome.getId(); + } catch (Throwable ignored) { + return -1; + } + } + + @Override + public String[] getBiomeList() { + ArrayList biomes = new ArrayList<>(); + for (Field field : Biome.class.getDeclaredFields()) { + if (field.getName().equals(field.getName().toUpperCase())) { + biomes.add(field.getName()); + } + } + return biomes.toArray(new String[biomes.size()]); + } + + @Override + public boolean addItems(String worldName, PlotItem items) { + return false; + } + + @Override + public boolean isBlockSolid(PlotBlock block) { + try { + Item item = Item.get(block.id, (int) block.data); + return (item != null && item.canBePlaced() && !Block.transparent[item.getId()] && Block.solid[item.getId()]); + } catch (Exception ignored) { + ignored.printStackTrace(); + return false; + } + } + + @Override + public String getClosestMatchingName(PlotBlock block) { + try { + return Item.get(block.id, (int) block.data).getName(); + } catch (Exception ignored) { + return null; + } + } + + @Override + public StringComparison.ComparisonResult getClosestBlock(String name) { + try { + Item item = Item.fromString(name); + return new StringComparison().new ComparisonResult(0, PlotBlock.get(item.getId(), item.getDamage())); + } catch (IllegalArgumentException ignored) {} + try { + byte data; + 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 { + StringComparison.ComparisonResult comparison = new StringComparison<>(name, Item.getCreativeItems()).getBestMatchAdvanced(); + match = comparison.match; + id = (short) comparison.best.getId(); + } + PlotBlock block = PlotBlock.get(id, data); + StringComparison outer = new StringComparison<>(); + return outer.new ComparisonResult(match, block); + + } catch (NumberFormatException ignored) {} + return null; + } + + @Override + public void setBiomes(String worldName, RegionWrapper region, String biomeString) { + Level world = getWorld(worldName); + try { + int biome = (int) Biome.class.getDeclaredField(biomeString.toUpperCase()).get(null); + for (int x = region.minX; x <= region.maxX; x++) { + for (int z = region.minZ; z <= region.maxZ; z++) { + world.setBiomeId(x, z, biome); + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + @Override + public PlotBlock getBlock(Location location) { + Level world = getWorld(location.getWorld()); + int id = world.getBlockIdAt(location.getX(), location.getY(), location.getZ()); + if (id == 0) { + return PlotBlock.get(0, 0); + } + int data = world.getBlockDataAt(location.getX(), location.getY(), location.getZ()); + return PlotBlock.get(id, data); + } + + @Override + public String getMainWorld() { + return plugin.getServer().getDefaultLevel().getName(); + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/util/block/NukkitHybridGen.java b/Nukkit/src/main/java/com/plotsquared/nukkit/util/block/NukkitHybridGen.java new file mode 100644 index 000000000..ee72b62bb --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/util/block/NukkitHybridGen.java @@ -0,0 +1,30 @@ +package com.plotsquared.nukkit.util.block; + +import cn.nukkit.level.Level; +import com.intellectualcrafters.plot.PS; +import com.intellectualcrafters.plot.generator.HybridGen; +import com.plotsquared.nukkit.NukkitMain; +import com.plotsquared.nukkit.generator.NukkitPlotGenerator; +import java.util.Map; + +public class NukkitHybridGen extends NukkitPlotGenerator { + public NukkitHybridGen(Map settings) { + super(defaultSettings(settings)); + } + + private static Map defaultSettings(Map existing) { + if (!existing.containsKey("world")) { + Map levels = ((NukkitMain) PS.get().IMP).getServer().getLevels(); + int max = -1; + for (Map.Entry entry : levels.entrySet()) { + int id = entry.getKey(); + if (id > max) { + max = id; + existing.put("world", entry.getValue().getName()); + } + } + } + existing.put("plot-generator", new HybridGen()); + return existing; + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/util/block/NukkitLocalQueue.java b/Nukkit/src/main/java/com/plotsquared/nukkit/util/block/NukkitLocalQueue.java new file mode 100644 index 000000000..d19e74db8 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/util/block/NukkitLocalQueue.java @@ -0,0 +1,125 @@ +package com.plotsquared.nukkit.util.block; + +import cn.nukkit.block.Block; +import cn.nukkit.level.Level; +import cn.nukkit.level.format.FullChunk; +import cn.nukkit.level.format.generic.BaseFullChunk; +import cn.nukkit.level.generator.biome.Biome; +import cn.nukkit.math.Vector3; +import com.intellectualcrafters.plot.PS; +import com.intellectualcrafters.plot.object.PlotBlock; +import com.intellectualcrafters.plot.util.StringMan; +import com.intellectualcrafters.plot.util.block.BasicLocalBlockQueue; +import com.plotsquared.nukkit.NukkitMain; + +public class NukkitLocalQueue extends BasicLocalBlockQueue { + + private final Level level; + + public NukkitLocalQueue(String world) { + super(world); + this.level = ((NukkitMain) PS.get().IMP).getServer().getLevelByName(world); + } + + @Override + public LocalChunk getLocalChunk(int x, int z) { + return (LocalChunk) new BasicLocalChunk(this, x, z) { + // Custom stuff? + }; + } + + @Override + public void optimize() { + + } + + @Override + public PlotBlock getBlock(int x, int y, int z) { + Block block = level.getBlock(getMut(x, y, z)); + if (block == null) { + return PlotBlock.get(0, 0); + } + int id = block.getId(); + if (id == 0) { + return PlotBlock.get(0, 0); + } + return PlotBlock.get(id, block.getDamage()); + } + + @Override + public void refreshChunk(int x, int z) { + + } + + @Override + public void fixChunkLighting(int x, int z) { + // Do nothing + } + + @Override + public final void regenChunk(int x, int z) { + level.regenerateChunk(x, z); + } + + @Override + public final void setComponents(LocalChunk lc) { + setBlocks(lc); + setBiomes(lc); + } + + public BaseFullChunk getChunk(int x, int z) { + return level.getChunk(x, z); + } + + private Vector3 mutable; + private Vector3 getMut(int x, int y, int z) { + mutable.x = x; + mutable.y = y; + mutable.z = z; + return mutable; + } + + public void setBlocks(LocalChunk lc) { + FullChunk chunk = level.getChunk(lc.getX(), lc.getZ(), true); + for (int layer = 0; layer < lc.blocks.length; layer++) { + PlotBlock[] blocksLayer = (PlotBlock[]) lc.blocks[layer]; + if (blocksLayer != null) { + int by = layer << 4; + int j = 0; + for (int y = by; y < by + 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++, j++) { + PlotBlock block = blocksLayer[j]; + if (block != null) { + chunk.setBlock(x, y, z, (int) block.id, (int) block.data); + } + } + } + } + } + } + } + + public void setBiomes(LocalChunk lc) { + if (lc.biomes != null) { + int bx = lc.getX() << 4; + int bz = lc.getX() << 4; + String last = null; + int biome = -1; + for (int x = 0; x < lc.biomes.length; x++) { + String[] biomes2 = lc.biomes[x]; + if (biomes2 != null) { + for (int y = 0; y < biomes2.length; y++) { + String biomeStr = biomes2[y]; + if (biomeStr != null) { + if (last == null || !StringMan.isEqual(last, biomeStr)) { + biome = Biome.getBiome(biomeStr.toUpperCase()).getId(); + } + level.setBiomeId(bx + x, bz + y, biome); + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/util/block/NukkitWrappedChunk.java b/Nukkit/src/main/java/com/plotsquared/nukkit/util/block/NukkitWrappedChunk.java new file mode 100644 index 000000000..6daf07f67 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/util/block/NukkitWrappedChunk.java @@ -0,0 +1,93 @@ +package com.plotsquared.nukkit.util.block; + +import cn.nukkit.level.format.generic.BaseFullChunk; +import cn.nukkit.level.generator.biome.Biome; +import com.intellectualcrafters.plot.object.Location; +import com.intellectualcrafters.plot.object.PlotBlock; +import com.intellectualcrafters.plot.util.block.ScopedLocalBlockQueue; +import java.awt.Color; + +public class NukkitWrappedChunk extends ScopedLocalBlockQueue { + private final String world; + private BaseFullChunk chunk; + + public NukkitWrappedChunk(String world, BaseFullChunk chunk) { + super(null, new Location(null, 0, 0, 0), new Location(null, 15, 127, 15)); + this.world = world; + init(chunk); + } + + public void init(BaseFullChunk chunk) { + this.chunk = chunk; + } + + @Override + public boolean setBlock(int x, int y, int z, int id, int data) { + chunk.setBlock(x, y, z, id, data); + return true; + } + + @Override + public PlotBlock getBlock(int x, int y, int z) { + int id = chunk.getBlockId(x, y, z); + if (id == 0) { + return PlotBlock.get(0, 0); + } + int data = chunk.getBlockData(x, y, z); + return PlotBlock.get(id, data); + } + + @Override + public boolean setBiome(int x, int z, String biome) { + Biome b = Biome.getBiome(biome); + int id = b.getId(); + Color color = new Color(b.getColor()); + chunk.setBiomeId(x, z, id); + chunk.setBiomeColor(x, z, color.getRed(), color.getGreen(), color.getBlue()); + return true; + } + + @Override + public void fillBiome(String biome) { + Biome b = Biome.getBiome(biome); + int id = b.getId(); + Color color = new Color(b.getColor()); + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + chunk.setBiomeId(x, z, id); + chunk.setBiomeColor(x, z, color.getRed(), color.getGreen(), color.getBlue()); + } + } + } + + @Override + public String getWorld() { + return world; + } + + public int getX() { + return chunk.getX(); + } + + public int getZ() { + return chunk.getZ(); + } + + @Override + public Location getMax() { + return new Location(getWorld(), 15 + (getX() << 4), 255, 15 + (getZ() << 4)); + } + + @Override + public Location getMin() { + return new Location(getWorld(), getX() << 4, 0, getZ() << 4); + } + + public NukkitWrappedChunk clone() { + return new NukkitWrappedChunk(world, chunk); + } + + public NukkitWrappedChunk shallowClone() { + return new NukkitWrappedChunk(world, chunk); + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/uuid/DatFileFilter.java b/Nukkit/src/main/java/com/plotsquared/nukkit/uuid/DatFileFilter.java new file mode 100644 index 000000000..c2bb3b938 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/uuid/DatFileFilter.java @@ -0,0 +1,12 @@ +package com.plotsquared.nukkit.uuid; + +import java.io.File; +import java.io.FilenameFilter; + +public class DatFileFilter implements FilenameFilter { + + @Override + public boolean accept(File dir, String name) { + return name.endsWith(".dat"); + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/uuid/FileUUIDHandler.java b/Nukkit/src/main/java/com/plotsquared/nukkit/uuid/FileUUIDHandler.java new file mode 100644 index 000000000..5260da4c9 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/uuid/FileUUIDHandler.java @@ -0,0 +1,63 @@ +package com.plotsquared.nukkit.uuid; + +import com.google.common.collect.HashBiMap; +import com.intellectualcrafters.plot.PS; +import com.intellectualcrafters.plot.config.C; +import com.intellectualcrafters.plot.object.RunnableVal; +import com.intellectualcrafters.plot.object.StringWrapper; +import com.intellectualcrafters.plot.util.TaskManager; +import com.intellectualcrafters.plot.util.UUIDHandlerImplementation; +import com.intellectualcrafters.plot.util.expiry.ExpireManager; +import com.intellectualcrafters.plot.uuid.UUIDWrapper; +import java.io.File; +import java.util.HashMap; +import java.util.UUID; + +public class FileUUIDHandler extends UUIDHandlerImplementation { + + public FileUUIDHandler(UUIDWrapper wrapper) { + super(wrapper); + } + + @Override + public boolean startCaching(Runnable whenDone) { + return super.startCaching(whenDone) && cache(whenDone); + } + + public boolean cache(final Runnable whenDone) { + final File container = new File("players"); + TaskManager.runTaskAsync(new Runnable() { + @Override + public void run() { + PS.debug(C.PREFIX + "&6Starting player data caching for: " + container); + HashBiMap toAdd = HashBiMap.create(new HashMap()); + for (File file : container.listFiles(new DatFileFilter())) { + String fileName = file.getName(); + String name = fileName.substring(0, fileName.length() - 4); + UUID uuid = uuidWrapper.getUUID(name); + toAdd.put(new StringWrapper(name), uuid); + long last = file.lastModified(); + if (ExpireManager.IMP != null) { + ExpireManager.IMP.storeDate(uuid, last); + } + } + add(toAdd); + if (whenDone != null) { + whenDone.run(); + } + } + }); + return true; + } + + @Override + public void fetchUUID(final String name, final RunnableVal ifFetch) { + TaskManager.runTaskAsync(new Runnable() { + @Override + public void run() { + ifFetch.value = FileUUIDHandler.this.uuidWrapper.getUUID(name); + TaskManager.runTask(ifFetch); + } + }); + } +} diff --git a/Nukkit/src/main/java/com/plotsquared/nukkit/uuid/LowerOfflineUUIDWrapper.java b/Nukkit/src/main/java/com/plotsquared/nukkit/uuid/LowerOfflineUUIDWrapper.java new file mode 100644 index 000000000..72b6b05f6 --- /dev/null +++ b/Nukkit/src/main/java/com/plotsquared/nukkit/uuid/LowerOfflineUUIDWrapper.java @@ -0,0 +1,41 @@ +package com.plotsquared.nukkit.uuid; + +import com.google.common.base.Charsets; +import com.intellectualcrafters.plot.object.OfflinePlotPlayer; +import com.intellectualcrafters.plot.object.PlotPlayer; +import com.intellectualcrafters.plot.uuid.UUIDWrapper; +import java.util.UUID; + +public class LowerOfflineUUIDWrapper extends UUIDWrapper { + + @Override + public UUID getUUID(PlotPlayer player) { + return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getName().toLowerCase()).getBytes(Charsets.UTF_8)); + } + + @Override + public UUID getUUID(OfflinePlotPlayer player) { + return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getName().toLowerCase()).getBytes(Charsets.UTF_8)); + } + + @Override + public UUID getUUID(String name) { + return UUID.nameUUIDFromBytes(("OfflinePlayer:" + name.toLowerCase()).getBytes(Charsets.UTF_8)); + } + + @Override + public OfflinePlotPlayer getOfflinePlayer(UUID uuid) { + return null; + } + + @Override + public OfflinePlotPlayer getOfflinePlayer(String name) { + return null; + } + + @Override + public OfflinePlotPlayer[] getOfflinePlayers() { + return new OfflinePlotPlayer[0]; + } + +} diff --git a/Nukkit/src/main/resources/plugin.yml b/Nukkit/src/main/resources/plugin.yml new file mode 100644 index 000000000..e0e4732da --- /dev/null +++ b/Nukkit/src/main/resources/plugin.yml @@ -0,0 +1,6 @@ +name: "${name}" +version: "${version}" +author: Empire92 +api: ["1.0.0"] +main: com.plotsquared.nukkit.NukkitMain +load: STARTUP \ No newline at end of file diff --git a/Sponge/src/main/java/com/plotsquared/sponge/SpongeMain.java b/Sponge/src/main/java/com/plotsquared/sponge/SpongeMain.java index 90b3cd08d..cfda08219 100644 --- a/Sponge/src/main/java/com/plotsquared/sponge/SpongeMain.java +++ b/Sponge/src/main/java/com/plotsquared/sponge/SpongeMain.java @@ -136,7 +136,7 @@ public class SpongeMain implements IPlotMain { THIS = this; new PS(this, "Sponge"); this.server = this.game.getServer(); - this.game.getRegistry().register(WorldGeneratorModifier.class, (WorldGeneratorModifier) new HybridGen().specify()); + this.game.getRegistry().register(WorldGeneratorModifier.class, (WorldGeneratorModifier) new HybridGen().specify(null)); } @Override @@ -394,7 +394,7 @@ public class SpongeMain implements IPlotMain { } @Override - public GeneratorWrapper wrapPlotGenerator(IndependentPlotGenerator generator) { + public GeneratorWrapper wrapPlotGenerator(String world, IndependentPlotGenerator generator) { return new SpongePlotGenerator(generator); } diff --git a/build.gradle b/build.gradle index 2f02607d9..0ef30476a 100644 --- a/build.gradle +++ b/build.gradle @@ -42,6 +42,7 @@ subprojects { } repositories { mavenCentral() + maven {url "http://ci.regularbox.com/plugin/repository/everything/"} maven {url "http://empcraft.com/maven2"} maven {url "http://repo.mcstats.org/content/repositories/public"} maven {url "http://maven.sk89q.com/repo/"} diff --git a/settings.gradle b/settings.gradle index cc0693084..11ad32b30 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,3 @@ rootProject.name = 'PlotSquared' -include 'Core', 'Bukkit', 'Sponge' \ No newline at end of file +include 'Core', 'Bukkit', 'Sponge', 'Nukkit' \ No newline at end of file