* Remove unused imports

* Implements PaperLib within bentobox

* Added PaperLib methods to Util for addons to call

* Uses PaperLib for island deletion

* Point to https://github.com/BentoBoxWorld/MVdWPlaceholderAPI in POM
This commit is contained in:
tastybento 2019-11-13 15:10:33 -08:00 committed by GitHub
parent e2fd5555cf
commit c9b0c74d08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 392 additions and 181 deletions

65
pom.xml
View File

@ -41,7 +41,7 @@
<ciManagement>
<system>jenkins</system>
<url>http://ci.codemc.org/job/BentoBoxWorld/job/BentoBox</url>
<url>https://ci.codemc.org/job/BentoBoxWorld/job/BentoBox</url>
</ciManagement>
<issueManagement>
@ -88,7 +88,8 @@
<profiles>
<profile>
<!-- ci profile is activated if exist environment variable BUILD_NUMBER. -->
<!-- It replaces ${build.number} that is currently '-LOCAL' with correct build number from JENKINS machine. -->
<!-- It replaces ${build.number} that is currently '-LOCAL' with
correct build number from JENKINS machine. -->
<id>ci</id>
<activation>
<property>
@ -101,10 +102,14 @@
</properties>
</profile>
<profile>
<!-- Master profile is activated if exist environment variable GIT_BRANCH and its value is origin/master. -->
<!-- It will replace 'revision' with '${build.version}' so it removes '-SNAPSHOT' string at the end. -->
<!-- Also, as this is release build, build number can be set to empty string. -->
<!-- This profile will be used only if exist environment variable GIT_BRANCH with value origin/master. -->
<!-- Master profile is activated if exist environment variable
GIT_BRANCH and its value is origin/master. -->
<!-- It will replace 'revision' with '${build.version}' so it
removes '-SNAPSHOT' string at the end. -->
<!-- Also, as this is release build, build number can be set
to empty string. -->
<!-- This profile will be used only if exist environment variable
GIT_BRANCH with value origin/master. -->
<id>master</id>
<activation>
<property>
@ -115,7 +120,7 @@
<properties>
<!-- Override only if necessary -->
<revision>${build.version}</revision>
<!-- Empties build number variable.-->
<!-- Empties build number variable. -->
<build.number></build.number>
</properties>
</profile>
@ -161,15 +166,19 @@
</repository>
<repository>
<id>placeholderapi-repo</id>
<url>http://repo.extendedclip.com/content/repositories/placeholderapi/</url>
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
</repository>
<repository>
<id>dynmap-repo</id>
<url>http://repo.mikeprimm.com/</url>
<url>https://repo.mikeprimm.com/</url>
</repository>
<repository>
<id>worldedit-repo</id>
<url>http://maven.sk89q.com/repo/</url>
<url>https://maven.sk89q.com/repo/</url>
</repository>
<repository>
<id>papermc</id>
<url>https://papermc.io/repo/repository/maven-public/</url>
</repository>
</repositories>
@ -228,11 +237,10 @@
<scope>provided</scope>
</dependency>
<dependency>
<!-- We have to use a forked version of this api
because Maxim had the brilliant idea to make one
of the dependencies rely on an illegal artifact
thus making its repository unusable. -->
<groupId>com.github.Prouser123-forks</groupId>
<!-- We have to use a forked version of this api because Maxim
had the brilliant idea to make one of the dependencies rely on an illegal
artifact thus making its repository unusable. -->
<groupId>com.github.BentoBoxWorld</groupId>
<artifactId>MVdWPlaceholderAPI</artifactId>
<version>${mvdwplaceholderapi.version}</version>
</dependency>
@ -256,23 +264,32 @@
<version>${githubapi.version}</version>
</dependency>
<!-- Static analysis -->
<!-- We are using Eclipse's annotations.
If you're using IDEA, update your project settings to take these
into account for in real time static analysis -->
<!-- We are using Eclipse's annotations. If you're using IDEA, update
your project settings to take these into account for in real time static
analysis -->
<dependency>
<groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.annotation</artifactId>
<version>2.2.200</version>
</dependency>
<!-- PaperLib -->
<dependency>
<groupId>io.papermc</groupId>
<artifactId>paperlib</artifactId>
<version>1.0.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<!-- By default ${revision} is ${build.version}-SNAPSHOT -->
<!-- If GIT_BRANCH variable is set to origin/master, then it will be only ${build.version}. -->
<!-- If GIT_BRANCH variable is set to origin/master, then it will
be only ${build.version}. -->
<!-- By default ${build.number} is -LOCAL. -->
<!-- If the BUILD_NUMBER variable is set, then it will be -b[number]. -->
<!-- If GIT_BRANCH variable is set to origin/master, then it will be the empty string. -->
<!-- If GIT_BRANCH variable is set to origin/master, then it will
be the empty string. -->
<finalName>${project.name}-${revision}${build.number}</finalName>
<defaultGoal>clean package</defaultGoal>
@ -350,6 +367,10 @@
<pattern>io.github.TheBusyBiscuit.GitHubWebAPI4Java</pattern>
<shadedPattern>world.bentobox.bentobox.api.github</shadedPattern>
</relocation>
<relocation>
<pattern>io.papermc.lib</pattern>
<shadedPattern>world.bentobox.bentobox.paperlib</shadedPattern> <!-- Replace this -->
</relocation>
</relocations>
<artifactSet>
<excludes>
@ -384,8 +405,8 @@
<configuration>
<append>true</append>
<excludes>
<!-- This is required to prevent Jacoco from adding synthetic fields
to a JavaBean class (causes errors in testing) -->
<!-- This is required to prevent Jacoco from adding
synthetic fields to a JavaBean class (causes errors in testing) -->
<exclude>**/*Names*</exclude>
</excludes>
</configuration>

View File

@ -3,7 +3,6 @@ package world.bentobox.bentobox.listeners;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import org.bukkit.Bukkit;
@ -15,7 +14,6 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.scheduler.BukkitRunnable;
import org.eclipse.jdt.annotation.NonNull;
import world.bentobox.bentobox.BentoBox;

View File

@ -12,6 +12,7 @@ import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.vehicle.VehicleMoveEvent;
import org.bukkit.util.Vector;
import io.papermc.lib.PaperLib;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.flags.FlagListener;
import world.bentobox.bentobox.api.user.User;
@ -155,7 +156,7 @@ public class LockAndBanListener extends FlagListener {
} else {
// There's nothing much we can do.
// We'll try to teleport him to the spawn...
player.teleport(player.getWorld().getSpawnLocation());
PaperLib.teleportAsync(player, player.getWorld().getSpawnLocation());
// Switch him back to the default gamemode. He may die, sorry :(
player.setGameMode(getIWM().getDefaultGameMode(player.getWorld()));

View File

@ -20,6 +20,7 @@ import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.TreeSpecies;
import org.bukkit.World;
import org.bukkit.attribute.Attribute;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
@ -36,6 +37,7 @@ import org.eclipse.jdt.annotation.Nullable;
import com.google.common.collect.ImmutableMap;
import io.papermc.lib.PaperLib;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.events.IslandBaseEvent;
import world.bentobox.bentobox.api.events.island.IslandEvent;
@ -664,27 +666,26 @@ public class IslandsManager {
.build();
return;
}
if (!home.getChunk().isLoaded()) {
home.getChunk().load();
}
player.teleport(home);
// Add home
if (plugin.getPlayers().getHomeLocations(world, player.getUniqueId()).isEmpty()) {
plugin.getPlayers().setHomeLocation(player.getUniqueId(), home);
}
if (number == 1) {
user.sendMessage("commands.island.go.teleport");
} else {
PaperLib.teleportAsync(player, home).thenAccept(b -> teleported(world, user, number, newIsland));
}
private void teleported(World world, User user, int number, boolean newIsland) {
if (number > 1) {
user.sendMessage("commands.island.go.teleported", TextVariables.NUMBER, String.valueOf(number));
}
// If this is a new island, then run commands and do resets
if (newIsland) {
// Execute commands
plugin.getIWM().getOnJoinCommands(world).forEach(command -> {
command = command.replace("[player]", player.getName());
command = command.replace("[player]", user.getName());
if (command.startsWith("[SUDO]")) {
// Execute the command by the player
player.performCommand(command.substring(6));
user.performCommand(command.substring(6));
} else {
// Otherwise execute as the server console
plugin.getServer().dispatchCommand(Bukkit.getConsoleSender(), command);
@ -704,7 +705,7 @@ public class IslandsManager {
// Reset the health
if (plugin.getIWM().isOnJoinResetHealth(world)) {
user.getPlayer().setHealth(20.0D);
user.getPlayer().setHealth(user.getPlayer().getAttribute(Attribute.GENERIC_MAX_HEALTH).getDefaultValue());
}
// Reset the hunger
@ -986,7 +987,7 @@ public class IslandsManager {
// Move player to spawn
if (spawn.containsKey(w)) {
// go to island spawn
p.teleport(spawn.get(w).getSpawnPoint(w.getEnvironment()));
PaperLib.teleportAsync(p, spawn.get(w).getSpawnPoint(w.getEnvironment()));
}
}
});

View File

@ -9,7 +9,6 @@ import org.bukkit.ChatColor;
import org.eclipse.jdt.annotation.NonNull;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;

View File

@ -5,6 +5,8 @@ import java.util.Random;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.generator.ChunkGenerator;
@ -12,6 +14,7 @@ import org.bukkit.generator.ChunkGenerator.ChunkData;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.scheduler.BukkitTask;
import io.papermc.lib.PaperLib;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.events.island.IslandEvent;
@ -25,13 +28,11 @@ import world.bentobox.bentobox.database.objects.IslandDeletion;
*/
public class DeleteIslandChunks {
/**
* This is how many chunks per world will be done in one tick.
*/
private int chunkX;
private int chunkZ;
private BukkitTask task;
private IslandDeletion di;
private boolean inDelete;
public DeleteIslandChunks(BentoBox plugin, IslandDeletion di) {
// Fire event
@ -42,16 +43,19 @@ public class DeleteIslandChunks {
this.di = di;
// Run through all chunks of the islands and regenerate them.
task = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
if (inDelete) return;
inDelete = true;
for (int i = 0; i < plugin.getSettings().getDeleteSpeed(); i++) {
plugin.getIWM().getAddon(di.getWorld()).ifPresent(gm -> {
Chunk chunk = di.getWorld().getChunkAt(chunkX, chunkZ);
regenerateChunk(gm, chunk);
// Overworld
processChunk(gm, di.getWorld(), chunkX, chunkZ);
// Nether
if (plugin.getIWM().isNetherGenerate(di.getWorld()) && plugin.getIWM().isNetherIslands(di.getWorld())) {
regenerateChunk(gm, plugin.getIWM().getNetherWorld(di.getWorld()).getChunkAt(chunkX, chunkZ));
processChunk(gm, plugin.getIWM().getNetherWorld(di.getWorld()), chunkX, chunkZ);
}
// End
if (plugin.getIWM().isEndGenerate(di.getWorld()) && plugin.getIWM().isEndIslands(di.getWorld())) {
regenerateChunk(gm, plugin.getIWM().getEndWorld(di.getWorld()).getChunkAt(chunkX, chunkZ));
processChunk(gm, plugin.getIWM().getEndWorld(di.getWorld()), chunkX, chunkZ);
}
chunkZ++;
if (chunkZ > di.getMaxZChunk()) {
@ -66,9 +70,16 @@ public class DeleteIslandChunks {
}
});
}
inDelete = false;
}, 0L, 1L);
}
private void processChunk(GameModeAddon gm, World world, int x, int z) {
if (PaperLib.isChunkGenerated(world, x, z)) {
PaperLib.getChunkAtAsync(world, x, z).thenAccept(chunk -> regenerateChunk(gm, chunk));
}
}
private void regenerateChunk(GameModeAddon gm, Chunk chunk) {
boolean isLoaded = chunk.isLoaded();
// Clear all inventories
@ -88,6 +99,9 @@ public class DeleteIslandChunks {
if (di.inBounds(baseX + x, baseZ + z)) {
chunk.getBlock(x, 0, z).setBiome(grid.getBiome(x, z));
for (int y = 0; y < chunk.getWorld().getMaxHeight(); y++) {
// Note: setting block to air before setting it to something else stops a bug in the server
// where it reports a "
chunk.getBlock(x, y, z).setType(Material.AIR, false);
chunk.getBlock(x, y, z).setBlockData(cd.getBlockData(x, y, z), false);
}
}

View File

@ -6,14 +6,19 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Animals;
import org.bukkit.entity.Bat;
@ -28,10 +33,13 @@ import org.bukkit.entity.Shulker;
import org.bukkit.entity.Slime;
import org.bukkit.entity.Snowman;
import org.bukkit.entity.WaterMob;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.util.Vector;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import io.papermc.lib.PaperLib;
import io.papermc.lib.features.blockstatesnapshot.BlockStateSnapshotResult;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.user.User;
@ -351,4 +359,164 @@ public class Util {
return entity instanceof Animals || entity instanceof IronGolem || entity instanceof Snowman ||
entity instanceof WaterMob && !(entity instanceof PufferFish) || entity instanceof Bat;
}
/*
* PaperLib methods for addons to call
*/
/**
* Teleports an Entity to the target location, loading the chunk asynchronously first if needed.
* @param entity The Entity to teleport
* @param location The Location to Teleport to
* @return Future that completes with the result of the teleport
*/
@Nonnull
public static CompletableFuture<Boolean> teleportAsync(@Nonnull Entity entity, @Nonnull Location location) {
return PaperLib.teleportAsync(entity, location);
}
/**
* Teleports an Entity to the target location, loading the chunk asynchronously first if needed.
* @param entity The Entity to teleport
* @param location The Location to Teleport to
* @param cause The cause for the teleportation
* @return Future that completes with the result of the teleport
*/
@Nonnull
public static CompletableFuture<Boolean> teleportAsync(@Nonnull Entity entity, @Nonnull Location location, TeleportCause cause) {
return PaperLib.teleportAsync(entity, location, cause);
}
/**
* Gets the chunk at the target location, loading it asynchronously if needed.
* @param loc Location to get chunk for
* @return Future that completes with the chunk
*/
@Nonnull
public static CompletableFuture<Chunk> getChunkAtAsync(@Nonnull Location loc) {
return getChunkAtAsync(loc.getWorld(), loc.getBlockX() >> 4, loc.getBlockZ() >> 4, true);
}
/**
* Gets the chunk at the target location, loading it asynchronously if needed.
* @param loc Location to get chunk for
* @param gen Should the chunk generate or not. Only respected on some MC versions, 1.13 for CB, 1.12 for Paper
* @return Future that completes with the chunk, or null if the chunk did not exists and generation was not requested.
*/
@Nonnull
public static CompletableFuture<Chunk> getChunkAtAsync(@Nonnull Location loc, boolean gen) {
return getChunkAtAsync(loc.getWorld(), loc.getBlockX() >> 4, loc.getBlockZ() >> 4, gen);
}
/**
* Gets the chunk at the target location, loading it asynchronously if needed.
* @param world World to load chunk for
* @param x X coordinate of the chunk to load
* @param z Z coordinate of the chunk to load
* @return Future that completes with the chunk
*/
@Nonnull
public static CompletableFuture<Chunk> getChunkAtAsync(@Nonnull World world, int x, int z) {
return getChunkAtAsync(world, x, z, true);
}
/**
* Gets the chunk at the target location, loading it asynchronously if needed.
* @param world World to load chunk for
* @param x X coordinate of the chunk to load
* @param z Z coordinate of the chunk to load
* @param gen Should the chunk generate or not. Only respected on some MC versions, 1.13 for CB, 1.12 for Paper
* @return Future that completes with the chunk, or null if the chunk did not exists and generation was not requested.
*/
@Nonnull
public static CompletableFuture<Chunk> getChunkAtAsync(@Nonnull World world, int x, int z, boolean gen) {
return PaperLib.getChunkAtAsync(world, x, z, gen);
}
/**
* Checks if the chunk has been generated or not. Only works on Paper 1.12+ or any 1.13.1+ version
* @param loc Location to check if the chunk is generated
* @return If the chunk is generated or not
*/
public static boolean isChunkGenerated(@Nonnull Location loc) {
return isChunkGenerated(loc.getWorld(), loc.getBlockX() >> 4, loc.getBlockZ() >> 4);
}
/**
* Checks if the chunk has been generated or not. Only works on Paper 1.12+ or any 1.13.1+ version
* @param world World to check for
* @param x X coordinate of the chunk to check
* @param z Z coordinate of the chunk to checl
* @return If the chunk is generated or not
*/
public static boolean isChunkGenerated(@Nonnull World world, int x, int z) {
return PaperLib.isChunkGenerated(world, x, z);
}
/**
* Get's a BlockState, optionally not using a snapshot
* @param block The block to get a State of
* @param useSnapshot Whether or not to use a snapshot when supported
* @return The BlockState
*/
@Nonnull
public static BlockStateSnapshotResult getBlockState(@Nonnull Block block, boolean useSnapshot) {
return PaperLib.getBlockState(block, useSnapshot);
}
/**
* Detects if the current MC version is at least the following version.
*
* Assumes 0 patch version.
*
* @param minor Min Minor Version
* @return Meets the version requested
*/
public static boolean isVersion(int minor) {
return PaperLib.isVersion(minor);
}
/**
* Detects if the current MC version is at least the following version.
* @param minor Min Minor Version
* @param patch Min Patch Version
* @return Meets the version requested
*/
public static boolean isVersion(int minor, int patch) {
return PaperLib.isVersion(minor, patch);
}
/**
* Gets the current Minecraft Minor version. IE: 1.13.1 returns 13
* @return The Minor Version
*/
public static int getMinecraftVersion() {
return PaperLib.getMinecraftVersion();
}
/**
* Gets the current Minecraft Patch version. IE: 1.13.1 returns 1
* @return The Patch Version
*/
public static int getMinecraftPatchVersion() {
return PaperLib.getMinecraftPatchVersion();
}
/**
* Check if the server has access to the Spigot API
* @return True for Spigot <em>and</em> Paper environments
*/
public static boolean isSpigot() {
return PaperLib.isSpigot();
}
/**
* Check if the server has access to the Paper API
* @return True for Paper environments
*/
public static boolean isPaper() {
return PaperLib.isPaper();
}
}

View File

@ -17,6 +17,7 @@ import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.Vector;
import org.eclipse.jdt.annotation.Nullable;
import io.papermc.lib.PaperLib;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
@ -226,16 +227,13 @@ public class SafeSpotTeleport {
*/
private void teleportEntity(final Location loc) {
task.cancel();
// Return to main thread and teleport the player
Bukkit.getScheduler().runTask(plugin, () -> {
if (!portal && entity instanceof Player && homeNumber > 0) {
// Set home if so marked
plugin.getPlayers().setHomeLocation(User.getInstance(entity), loc, homeNumber);
}
Vector velocity = entity.getVelocity();
entity.teleport(loc);
entity.setVelocity(velocity);
});
// Return to main thread and teleport the player
Bukkit.getScheduler().runTask(plugin, () -> PaperLib.teleportAsync(entity, loc).thenAccept(b -> entity.setVelocity(velocity)));
}
/**

View File

@ -66,6 +66,9 @@ import org.powermock.reflect.Whitebox;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import io.papermc.lib.PaperLib;
import io.papermc.lib.environments.CraftBukkitEnvironment;
import io.papermc.lib.environments.Environment;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.Settings;
import world.bentobox.bentobox.api.configuration.WorldSettings;
@ -131,6 +134,8 @@ public class IslandsManagerTest {
private Material sign;
private Material wallSign;
private Environment env;
/**
* @throws java.lang.Exception
@ -188,6 +193,8 @@ public class IslandsManagerTest {
BukkitScheduler sch = mock(BukkitScheduler.class);
PowerMockito.mockStatic(Bukkit.class);
when(Bukkit.getScheduler()).thenReturn(sch);
// version
when(Bukkit.getVersion()).thenReturn("Paper version git-Paper-225 (MC: 1.14.4) (Implementing API version 1.14.4-R0.1-SNAPSHOT)");
// Standard location
manager = new IslandsManager(plugin);
@ -295,6 +302,10 @@ public class IslandsManagerTest {
if (wallSign == null) {
wallSign = Material.getMaterial("OAK_WALL_SIGN");
}
// PaperLib
env = new CraftBukkitEnvironment();
PaperLib.setCustomEnvironment(env);
}
@After
@ -716,7 +727,7 @@ public class IslandsManagerTest {
when(pm.getHomeLocation(any(), any(User.class), eq(0))).thenReturn(null);
when(pm.getHomeLocation(any(), any(User.class), eq(1))).thenReturn(location);
im.homeTeleport(world, player, 0);
verify(player).teleport(location);
verify(player).teleport(eq(location), any());
}