1
0
mirror of https://github.com/BentoBoxWorld/Warps.git synced 2024-11-29 14:15:23 +01:00

Merge remote-tracking branch 'origin/develop'

This commit is contained in:
tastybento 2021-08-08 18:32:40 -07:00
commit 70457afe65
29 changed files with 704 additions and 586 deletions

View File

@ -1,26 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
---
**Description**
<!-- A clear and concise description of what the bug is. -->
**Steps to reproduce the behavior:**
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
<!-- A clear and concise description of what you expected to happen. -->
**Screenshots**
<!-- If applicable, add screenshots to help explain your problem. -->
**Server Information:**
Do `bbox version` in the console and paste the result here:
**Additional context**
<!-- Add any other context about the problem here. -->

View File

@ -1,17 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

38
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,38 @@
name: Build
on:
push:
branches:
- develop
- master
pull_request:
types: [opened, synchronize, reopened]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Set up JDK 16
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '16'
- name: Cache SonarCloud packages
uses: actions/cache@v2
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache Maven packages
uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Build and analyze
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar

View File

@ -1,21 +0,0 @@
language: java
sudo: false
addons:
sonarcloud:
organization: "bentobox-world"
jdk:
- openjdk8
- openjdk11
matrix:
allow_failures:
- jdk: openjdk11
script:
mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install sonar:sonar -Dsonar.projectKey=BentoBoxWorld_Warps
cache:
directories:
- '$HOME/.m2/repository'
- '$HOME/.sonar/cache'

View File

@ -5,6 +5,8 @@ to disable use by gamemode.
## How to use ## How to use
### Note: Java 16 and Minecraft 17, or later are required.
1. Place the jar in the addons folder of the BentoBox plugin 1. Place the jar in the addons folder of the BentoBox plugin
2. Restart the server 2. Restart the server
3. The addon will create a data folder and inside the folder will be a config.yml 3. The addon will create a data folder and inside the folder will be a config.yml

66
pom.xml
View File

@ -54,19 +54,23 @@
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version> <java.version>16</java.version>
<!-- Non-minecraft related dependencies --> <!-- Non-minecraft related dependencies -->
<powermock.version>2.0.2</powermock.version> <powermock.version>2.0.9</powermock.version>
<!-- More visible way how to change dependency versions --> <!-- More visible way how to change dependency versions -->
<spigot.version>1.16.3-R0.1-SNAPSHOT</spigot.version> <spigot.version>1.17-R0.1-SNAPSHOT</spigot.version>
<bentobox.version>1.15.4</bentobox.version> <bentobox.version>1.17.0</bentobox.version>
<level.version>1.5.0</level.version> <level.version>2.7.0-SNAPSHOT</level.version>
<!-- Revision variable removes warning about dynamic version --> <!-- Revision variable removes warning about dynamic version -->
<revision>${build.version}-SNAPSHOT</revision> <revision>${build.version}-SNAPSHOT</revision>
<!-- Do not change unless you want different name for local builds. --> <!-- Do not change unless you want different name for local builds. -->
<build.number>-LOCAL</build.number> <build.number>-LOCAL</build.number>
<!-- This allows to change between versions. --> <!-- This allows to change between versions. -->
<build.version>1.10.2</build.version> <build.version>1.11.1</build.version>
<!-- Sonar Cloud -->
<sonar.projectKey>BentoBoxWorld_Warps</sonar.projectKey>
<sonar.organization>bentobox-world</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
</properties> </properties>
<!-- Profiles will allow to automatically change build version. --> <!-- Profiles will allow to automatically change build version. -->
@ -109,30 +113,6 @@
<build.number></build.number> <build.number></build.number>
</properties> </properties>
</profile> </profile>
<profile>
<id>sonar</id>
<properties>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
<sonar.organization>bentobox-world</sonar.organization>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.6.0.1398</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>sonar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles> </profiles>
<repositories> <repositories>
@ -162,7 +142,7 @@
<dependency> <dependency>
<groupId>org.mockito</groupId> <groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId> <artifactId>mockito-core</artifactId>
<version>3.0.0</version> <version>3.11.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
@ -196,7 +176,7 @@
<dependency> <dependency>
<groupId>org.eclipse.jdt</groupId> <groupId>org.eclipse.jdt</groupId>
<artifactId>org.eclipse.jdt.annotation</artifactId> <artifactId>org.eclipse.jdt.annotation</artifactId>
<version>2.2.200</version> <version>2.2.600</version>
</dependency> </dependency>
</dependencies> </dependencies>
@ -246,7 +226,12 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version> <version>3.0.0-M5</version>
<configuration>
<argLine>
--illegal-access=permit
</argLine>
</configuration>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
@ -256,15 +241,18 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>3.0.1</version> <version>3.1.1</version>
<configuration> <configuration>
<show>public</show> <source>16</source>
<show>private</show>
<failOnError>false</failOnError> <failOnError>false</failOnError>
<additionalJOption>-Xdoclint:none</additionalJOption> <additionalJOption>-Xdoclint:none</additionalJOption>
<javadocExecutable>${java.home}/bin/javadoc</javadocExecutable>
</configuration> </configuration>
<executions> <executions>
<execution> <execution>
<id>attach-javadocs</id> <id>attach-javadocs</id>
<phase>install</phase>
<goals> <goals>
<goal>jar</goal> <goal>jar</goal>
</goals> </goals>
@ -284,14 +272,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<minimizeJar>false</minimizeJar>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId> <artifactId>maven-install-plugin</artifactId>

View File

@ -12,18 +12,28 @@ import com.google.gson.annotations.Expose;
* *
*/ */
public class SignCacheItem { public class SignCacheItem {
@Expose @Expose
private final List<String> signText; private final List<String> signText;
@Expose @Expose
private final Material type; private final Material type;
/** /**
* @param signText * @param signText sign text
* @param type * @param type material of sign
*/ */
public SignCacheItem(List<String> signText, Material type) { public SignCacheItem(List<String> signText, Material type) {
this.signText = signText; this.signText = signText;
this.type = type; this.type = type;
} }
/**
* This sign is not real
*/
public SignCacheItem() {
this.signText = null;
this.type = null;
}
/** /**
* @return the signText * @return the signText
*/ */
@ -36,5 +46,12 @@ public class SignCacheItem {
public Material getType() { public Material getType() {
return type; return type;
} }
/**
* @return the isReal
*/
public boolean isReal() {
return getType() != null;
}
} }

View File

@ -1,22 +1,22 @@
package world.bentobox.warps; package world.bentobox.warps;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.eclipse.jdt.annotation.NonNull;
import world.bentobox.bentobox.database.Database; import world.bentobox.bentobox.database.Database;
import world.bentobox.warps.objects.SignCache; import world.bentobox.warps.objects.SignCache;
public class SignCacheManager { public class SignCacheManager {
private Map<World, Map<UUID, SignCacheItem>> cachedSigns = new HashMap<>(); private final Map<World, Map<UUID, SignCacheItem>> cachedSigns = new HashMap<>();
private Warp addon; private final Warp addon;
// Database handler for level data // Database handler for level data
private Database<SignCache> handler; private final Database<SignCache> handler;
public SignCacheManager(Warp addon) { public SignCacheManager(Warp addon) {
this.addon = addon; this.addon = addon;
@ -26,9 +26,11 @@ public class SignCacheManager {
} }
private void loadCache() { private void loadCache() {
cachedSigns.clear();
handler.loadObjects().forEach(w -> { handler.loadObjects().forEach(w -> {
World world = Bukkit.getWorld(w.getUniqueId()); World world = Bukkit.getWorld(w.getUniqueId());
if (world != null) { if (world != null) {
w.getSigns().values().removeIf(sci -> sci.getType().equals(Material.AIR));
cachedSigns.put(world, w.getSigns()); cachedSigns.put(world, w.getSigns());
} }
}); });
@ -38,43 +40,41 @@ public class SignCacheManager {
cachedSigns.forEach((w, m) -> handler.saveObjectAsync(new SignCache(w, m))); cachedSigns.forEach((w, m) -> handler.saveObjectAsync(new SignCache(w, m)));
} }
Material getSignIcon(World world, UUID warpOwner) {
// Add the worlds if we haven't seen this before
cachedSigns.putIfAbsent(world, new HashMap<>());
if (cachedSigns.get(world).containsKey(warpOwner)) {
return cachedSigns.get(world).get(warpOwner).getType();
}
// Not in cache
SignCacheItem sc = addon.getWarpSignsManager().getSignInfo(world, warpOwner);
cachedSigns.get(world).put(warpOwner, sc);
return sc.getType();
}
/** /**
* Gets sign text and cache it * Get the sign item from cache or get it from the world if it is not in the cache
* @param playerUUID * @param world - world
* @return sign text in a list * @param warpOwner - warp owner
* @return SignCacheItem
*/ */
List<String> getSign(World world, UUID playerUUID) { @NonNull
SignCacheItem getSignItem(World world, UUID warpOwner) {
// Add the worlds if we haven't seen this before // Add the worlds if we haven't seen this before
cachedSigns.putIfAbsent(world, new HashMap<>()); cachedSigns.putIfAbsent(world, new HashMap<>());
if (cachedSigns.get(world).containsKey(playerUUID)) { // Get from cache if available
return cachedSigns.get(world).get(playerUUID).getSignText(); if (cachedSigns.get(world).containsKey(warpOwner)) {
return cachedSigns.get(world).get(warpOwner);
} }
SignCacheItem result = addon.getWarpSignsManager().getSignInfo(world, playerUUID); // Generate and add to cache
cachedSigns.get(world).put(playerUUID, result); SignCacheItem result = addon.getWarpSignsManager().getSignInfo(world, warpOwner);
return result.getSignText(); if (result.isReal()) {
cachedSigns.get(world).put(warpOwner, result);
} else {
cachedSigns.get(world).remove(warpOwner);
}
return result;
} }
/** /**
* Removes sign text from the cache * Removes sign text from the cache
* @param world - world * @param world - world
* @param key - uuid of owner * @param key - uuid of owner
* @return true if item is removed from cache
*/ */
void removeWarp(World world, UUID key) { boolean removeWarp(World world, UUID key) {
if (cachedSigns.containsKey(world)) { if (cachedSigns.containsKey(world)) {
cachedSigns.get(world).remove(key); return cachedSigns.get(world).remove(key) != null;
} }
return false;
} }
} }

View File

@ -104,7 +104,7 @@ public class Warp extends Addon {
this.warpSignsManager.saveWarpList(); this.warpSignsManager.saveWarpList();
this.loadSettings(); this.loadSettings();
this.getLogger().info("WelcomeWarp addon reloaded."); this.getLogger().info("Warps addon reloaded.");
} }
} }
@ -149,10 +149,9 @@ public class Warp extends Addon {
@Override @Override
public void onDisable(){ public void onDisable(){
// Save the warps // Save the warps
if (warpSignsManager != null) if (warpSignsManager != null) {
warpSignsManager.saveWarpList(); warpSignsManager.saveWarpList();
if (warpPanelManager != null) }
warpPanelManager.saveCache();
} }
@ -211,10 +210,18 @@ public class Warp extends Addon {
* Get the island level * Get the island level
* @param world - world * @param world - world
* @param uniqueId - player's UUID * @param uniqueId - player's UUID
* @return island level or null if there is no level plugin * @return island level or null if there is no level plugin or Level is not operating in this world
*/ */
public Long getLevel(World world, UUID uniqueId) { public Long getLevel(World world, UUID uniqueId) {
return this.getPlugin().getAddonsManager().getAddonByName(LEVEL_ADDON_NAME).map(l -> ((Level) l).getIslandLevel(world, uniqueId)).orElse(null); // Get name of the game mode
String name = this.getPlugin().getIWM().getAddon(world).map(g -> g.getDescription().getName()).orElse("");
return this.getPlugin().getAddonsManager().getAddonByName(LEVEL_ADDON_NAME)
.map(l -> {
if (!name.isEmpty() && ((Level) l).getSettings().getGameModes().contains(name)) {
return ((Level) l).getIslandLevel(world, uniqueId);
}
return null;
}).orElse(null);
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -241,20 +248,14 @@ public class Warp extends Addon {
return null; return null;
} }
} }
switch(requestLabel) { return switch (requestLabel) {
case "getSortedWarps": case "getSortedWarps" -> getWarpSignsManager().getSortedWarps(world);
return getWarpSignsManager().getSortedWarps(world); case "getWarp" -> uuid == null ? null : getWarpSignsManager().getWarp(world, uuid);
case "getWarp": case "getWarpMap" -> getWarpSignsManager().getWarpMap(world);
return uuid == null ? null : getWarpSignsManager().getWarp(world, uuid); case "hasWarp" -> uuid == null ? null : getWarpSignsManager().hasWarp(world, uuid);
case "getWarpMap": case "listWarps" -> getWarpSignsManager().listWarps(world);
return getWarpSignsManager().getWarpMap(world); default -> null;
case "hasWarp": };
return uuid == null ? null : getWarpSignsManager().hasWarp(world, uuid);
case "listWarps":
return getWarpSignsManager().listWarps(world);
default:
return null;
}
} }

View File

@ -1,13 +1,16 @@
package world.bentobox.warps; package world.bentobox.warps;
import java.util.ArrayList; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.eclipse.jdt.annotation.NonNull;
import world.bentobox.bentobox.api.panels.PanelItem; import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder; import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
@ -17,21 +20,22 @@ import world.bentobox.bentobox.api.user.User;
public class WarpPanelManager { public class WarpPanelManager {
private static final int PANEL_MAX_SIZE = 52; private static final int PANEL_MAX_SIZE = 52;
private Warp addon; private final Warp addon;
// This is a cache of signs // This is a cache of signs
private SignCacheManager signCacheManager; private final SignCacheManager signCacheManager;
public WarpPanelManager(Warp addon) { public WarpPanelManager(Warp addon) {
this.addon = addon; this.addon = addon;
signCacheManager = new SignCacheManager(addon); signCacheManager = new SignCacheManager(addon);
} }
private PanelItem getPanelItem(World world, UUID warpOwner) { private PanelItem getPanelItem(World world, UUID warpOwner, SignCacheItem sign) {
PanelItemBuilder pib = new PanelItemBuilder() PanelItemBuilder pib = new PanelItemBuilder()
.name(addon.getSettings().getNameFormat() + addon.getPlugin().getPlayers().getName(warpOwner)) .name(addon.getSettings().getNameFormat() + addon.getPlugin().getPlayers().getName(warpOwner))
.description(signCacheManager.getSign(world, warpOwner)) .description(sign.getSignText())
.clickHandler((panel, clicker, click, slot) -> hander(world, clicker, warpOwner)); .clickHandler((panel, clicker, click, slot) -> hander(world, clicker, warpOwner));
Material icon = signCacheManager.getSignIcon(world, warpOwner); Material icon = sign.getType();
if (icon.equals(Material.PLAYER_HEAD)) { if (icon.equals(Material.PLAYER_HEAD)) {
return pib.icon(addon.getPlayers().getName(warpOwner)).build(); return pib.icon(addon.getPlayers().getName(warpOwner)).build();
} else { } else {
@ -41,15 +45,13 @@ public class WarpPanelManager {
private boolean hander(World world, User clicker, UUID warpOwner) { private boolean hander(World world, User clicker, UUID warpOwner) {
clicker.closeInventory(); clicker.closeInventory();
String playerCommand = addon.getPlugin().getIWM().getAddon(world).map(gm -> gm.getPlayerCommand().map(c -> c.getLabel()).orElse("")).orElse(""); String playerCommand = addon.getPlugin().getIWM().getAddon(world).map(gm -> gm.getPlayerCommand().map(Command::getLabel).orElse("")).orElse("");
String command = addon.getSettings().getWarpCommand() + " " + addon.getPlayers().getName(warpOwner); String command = addon.getSettings().getWarpCommand() + " " + addon.getPlayers().getName(warpOwner);
clicker.getPlayer().performCommand((playerCommand.isEmpty() ? "" : playerCommand + " ") + command); clicker.getPlayer().performCommand((playerCommand.isEmpty() ? "" : playerCommand + " ") + command);
//addon.getWarpSignsManager().warpPlayer(world, clicker, warpOwner);
return true; return true;
} }
private PanelItem getRandomButton(World world, User user, UUID warpOwner) { private PanelItem getRandomButton(World world, User user, UUID warpOwner) {
///give @p minecraft:player_head{display:{Name:"{\"text\":\"Question Mark\"}"},SkullOwner:"MHF_Question"} 1
return new PanelItemBuilder() return new PanelItemBuilder()
.name(addon.getSettings().getNameFormat() + user.getTranslation("warps.random")) .name(addon.getSettings().getNameFormat() + user.getTranslation("warps.random"))
.clickHandler((panel, clicker, click, slot) -> hander(world, clicker, warpOwner)) .clickHandler((panel, clicker, click, slot) -> hander(world, clicker, warpOwner))
@ -63,44 +65,87 @@ public class WarpPanelManager {
* @param index - page to show - 0 is first * @param index - page to show - 0 is first
*/ */
public void showWarpPanel(World world, User user, int index) { public void showWarpPanel(World world, User user, int index) {
List<UUID> warps = new ArrayList<>(addon.getWarpSignsManager().getSortedWarps(world));
UUID randomWarp = null; PanelBuilder panelBuilder = new PanelBuilder()
// Add random UUID .user(user)
.name(user.getTranslation("warps.title") + " " + (index + 1));
buildPanel(panelBuilder, user, index, world).thenRun(panelBuilder::build);
}
CompletableFuture<Void> buildPanel(PanelBuilder panelBuilder, User user, int index, World world) {
CompletableFuture<Void> r = new CompletableFuture<>();
processSigns(r, panelBuilder, user, index, world);
return r;
}
void processSigns(CompletableFuture<Void> r, PanelBuilder panelBuilder, User user, int index, World world) {
addon.getWarpSignsManager().getSortedWarps(world).thenAccept(warps -> {
// Cache and clean the signs
Iterator<UUID> it = warps.iterator();
while(it.hasNext()) {
UUID warpOwner = it.next();
@NonNull
SignCacheItem sign = signCacheManager.getSignItem(world, warpOwner);
if (!sign.isReal()) {
it.remove();
addon.getWarpSignsManager().removeWarpFromMap(world, warpOwner);
}
}
// Add random warp
getRandomWarp(warps);
// Build the main body
int i = buildMainBody(panelBuilder, user, index, world, warps);
// Add navigation
addNavigation(panelBuilder, user, world, i, index, warps.size());
r.complete(null);
});
}
private void getRandomWarp(List<UUID> warps) {
// Add random warp
if (!warps.isEmpty() && addon.getSettings().isRandomAllowed()) { if (!warps.isEmpty() && addon.getSettings().isRandomAllowed()) {
randomWarp = warps.get(new Random().nextInt(warps.size())); warps.add(0, warps.get(new Random().nextInt(warps.size())));
warps.add(0, randomWarp);
} }
}
int buildMainBody(PanelBuilder panelBuilder, User user, int index, World world, List<UUID> warps) {
if (index < 0) { if (index < 0) {
index = 0; index = 0;
} else if (index > (warps.size() / PANEL_MAX_SIZE)) { } else if (index > (warps.size() / PANEL_MAX_SIZE)) {
index = warps.size() / PANEL_MAX_SIZE; index = warps.size() / PANEL_MAX_SIZE;
} }
PanelBuilder panelBuilder = new PanelBuilder()
.user(user)
.name(user.getTranslation("warps.title") + " " + (index + 1));
int i = index * PANEL_MAX_SIZE; int i = index * PANEL_MAX_SIZE;
for (; i < (index * PANEL_MAX_SIZE + PANEL_MAX_SIZE) && i < warps.size(); i++) { for (; panelBuilder.getItems().size() < PANEL_MAX_SIZE && i < warps.size(); i++) {
if (i == 0 && randomWarp != null) { UUID warpOwner = warps.get(i);
panelBuilder.item(getRandomButton(world, user, randomWarp)); if (addon.getSettings().isRandomAllowed() && i == 0) {
panelBuilder.item(getRandomButton(world, user, warpOwner));
} else { } else {
panelBuilder.item(getPanelItem(world, warps.get(i))); @NonNull
SignCacheItem sign = signCacheManager.getSignItem(world, warpOwner);
if (sign.isReal()) {
panelBuilder.item(getPanelItem(world, warpOwner, sign));
} else {
addon.getWarpSignsManager().removeWarpFromMap(world, warpOwner);
}
} }
} }
final int panelNum = index; return i;
// Add signs }
if (i < warps.size()) {
// Next /**
panelBuilder.item(new PanelItemBuilder() * Add Next and Previous icons to navigate
.name(user.getTranslation("warps.next")) * @param panelBuilder - the panel builder
.icon(new ItemStack(Material.STONE)) * @param user - user
.clickHandler((panel, clicker, click, slot) -> { * @param world - world
user.closeInventory(); * @param numOfItems - number of items shown so far including in previous panels
showWarpPanel(world, user, panelNum+1); * @param panelNum - panel number (page)
return true; * @param totalNum - total number of items in the list
}).build()); */
} void addNavigation(PanelBuilder panelBuilder, User user, World world, int numOfItems, int panelNum, int totalNum) {
if (i > PANEL_MAX_SIZE) { // Previous
if (panelNum > 0 && numOfItems > PANEL_MAX_SIZE) {
// Previous // Previous
panelBuilder.item(new PanelItemBuilder() panelBuilder.item(new PanelItemBuilder()
.name(user.getTranslation("warps.previous")) .name(user.getTranslation("warps.previous"))
@ -111,16 +156,28 @@ public class WarpPanelManager {
return true; return true;
}).build()); }).build());
} }
panelBuilder.build(); // Next
if (numOfItems < totalNum) {
// Next
panelBuilder.item(new PanelItemBuilder()
.name(user.getTranslation("warps.next"))
.icon(new ItemStack(Material.STONE))
.clickHandler((panel, clicker, click, slot) -> {
user.closeInventory();
showWarpPanel(world, user, panelNum+1);
return true;
}).build());
}
} }
/** /**
* Removes sign text from the cache * Removes sign text from the cache
* @param world - world * @param world - world
* @param key - uuid of owner * @param key - uuid of owner
* @return true if the item was removed from the cache
*/ */
public void removeWarp(World world, UUID key) { public boolean removeWarp(World world, UUID key) {
signCacheManager.removeWarp(world, key); return signCacheManager.removeWarp(world, key);
} }
public void saveCache() { public void saveCache() {

View File

@ -3,16 +3,17 @@ package world.bentobox.warps;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -37,7 +38,6 @@ import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.lists.Flags; import world.bentobox.bentobox.lists.Flags;
import world.bentobox.bentobox.util.Util; import world.bentobox.bentobox.util.Util;
import world.bentobox.warps.event.WarpInitiateEvent; import world.bentobox.warps.event.WarpInitiateEvent;
import world.bentobox.warps.event.WarpListEvent;
import world.bentobox.warps.objects.WarpsData; import world.bentobox.warps.objects.WarpsData;
/** /**
@ -49,13 +49,13 @@ import world.bentobox.warps.objects.WarpsData;
public class WarpSignsManager { public class WarpSignsManager {
private static final int MAX_WARPS = 600; private static final int MAX_WARPS = 600;
private static final String WARPS = "warps"; private static final String WARPS = "warps";
private BentoBox plugin; private final BentoBox plugin;
// Map of all warps stored as player, warp sign Location // Map of all warps stored as player, warp sign Location
private Map<World, Map<UUID, Location>> worldsWarpList; private Map<World, Map<UUID, Location>> worldsWarpList;
// Database handler for level data // Database handler for level data
private Database<WarpsData> handler; private final Database<WarpsData> handler;
private Warp addon; private final Warp addon;
private WarpsData warpsData = new WarpsData(); private WarpsData warpsData = new WarpsData();
/** /**
@ -75,6 +75,7 @@ public class WarpSignsManager {
public WarpSignsManager(Warp addon, BentoBox plugin) { public WarpSignsManager(Warp addon, BentoBox plugin) {
this.addon = addon; this.addon = addon;
this.plugin = plugin; this.plugin = plugin;
this.worldsWarpList = new HashMap<>();
// Set up the database handler // Set up the database handler
// Note that these are saved by the BentoBox database // Note that these are saved by the BentoBox database
handler = new Database<>(addon, WarpsData.class); handler = new Database<>(addon, WarpsData.class);
@ -129,18 +130,32 @@ public class WarpSignsManager {
.findFirst().map(en -> plugin.getPlayers().getName(en.getKey())).orElse(""); .findFirst().map(en -> plugin.getPlayers().getName(en.getKey())).orElse("");
} }
/**
* Get the optional UUID of the warp owner by location
* @param location to search
* @return Optional UUID of warp owner or empty if there is none
*/
public Optional<UUID> getWarpOwnerUUID(Location location) {
return getWarpMap(location.getWorld()).entrySet().stream().filter(en -> en.getValue().equals(location))
.findFirst().map(Map.Entry::getKey);
}
/** /**
* Get sorted list of warps with most recent players listed first * Get sorted list of warps with most recent players listed first
* @return UUID list * @return UUID list
*/ */
@NonNull public CompletableFuture<List<UUID>> getSortedWarps(@NonNull World world) {
public List<UUID> getSortedWarps(@NonNull World world) { CompletableFuture<List<UUID>> r = new CompletableFuture<>();
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> processWarpMap(r, world));
return r;
}
List<UUID> processWarpMap(CompletableFuture<List<UUID>> r, @NonNull World world) {
// Remove any null locations - this can happen if an admin changes the name of the world and signs point to old locations // Remove any null locations - this can happen if an admin changes the name of the world and signs point to old locations
getWarpMap(world).values().removeIf(Objects::isNull); getWarpMap(world).values().removeIf(Objects::isNull);
// Bigger value of time means a more recent login // Bigger value of time means a more recent login
TreeMap<Long, UUID> map = new TreeMap<>(); TreeMap<Long, UUID> map = new TreeMap<>();
getWarpMap(world).entrySet().forEach(en -> { getWarpMap(world).forEach((uuid, value) -> {
UUID uuid = en.getKey();
// If never played, will be zero // If never played, will be zero
long lastPlayed = addon.getServer().getOfflinePlayer(uuid).getLastPlayed(); long lastPlayed = addon.getServer().getOfflinePlayer(uuid).getLastPlayed();
// This aims to avoid the chance that players logged off at exactly the same time // This aims to avoid the chance that players logged off at exactly the same time
@ -154,11 +169,8 @@ public class WarpSignsManager {
if (list.size() > MAX_WARPS) { if (list.size() > MAX_WARPS) {
list.subList(0, MAX_WARPS).clear(); list.subList(0, MAX_WARPS).clear();
} }
// Fire event // Return to main thread
WarpListEvent event = new WarpListEvent(addon, list); Bukkit.getScheduler().runTask(plugin, () -> r.complete(list));
Bukkit.getPluginManager().callEvent(event);
// Get the result of any changes by listeners
list = event.getWarps();
return list; return list;
} }
@ -172,7 +184,7 @@ public class WarpSignsManager {
public Set<UUID> listWarps(@NonNull World world) { public Set<UUID> listWarps(@NonNull World world) {
// Remove any null locations // Remove any null locations
getWarpMap(world).values().removeIf(Objects::isNull); getWarpMap(world).values().removeIf(Objects::isNull);
return getWarpMap(world).entrySet().stream().filter(e -> Util.sameWorld(world, e.getValue().getWorld())).map(Map.Entry::getKey).collect(Collectors.toSet()); return getWarpMap(world).entrySet().stream().filter(e -> Util.sameWorld(world, Objects.requireNonNull(e.getValue().getWorld()))).map(Map.Entry::getKey).collect(Collectors.toSet());
} }
/** /**
@ -204,7 +216,7 @@ public class WarpSignsManager {
/** /**
* Changes the sign to red if it exists * Changes the sign to red if it exists
* @param loc * @param loc location to pop
*/ */
private void popSign(Location loc) { private void popSign(Location loc) {
Block b = loc.getBlock(); Block b = loc.getBlock();
@ -220,7 +232,7 @@ public class WarpSignsManager {
/** /**
* Removes a warp at a location. * Removes a warp at a location.
* *
* @param loc * @param loc location to remove
*/ */
public void removeWarp(Location loc) { public void removeWarp(Location loc) {
popSign(loc); popSign(loc);
@ -245,7 +257,7 @@ public class WarpSignsManager {
/** /**
* Remove warp sign owned by UUID * Remove warp sign owned by UUID
* *
* @param uuid * @param uuid UUID of owner to remove
*/ */
public void removeWarp(World world, UUID uuid) { public void removeWarp(World world, UUID uuid) {
if (getWarpMap(world).containsKey(uuid)) { if (getWarpMap(world).containsKey(uuid)) {
@ -258,6 +270,15 @@ public class WarpSignsManager {
saveWarpList(); saveWarpList();
} }
/**
* Remove the warp from the warp map
* @param world - world
* @param uuid - uuid of owner
*/
public void removeWarpFromMap(World world, UUID uuid) {
getWarpMap(world).remove(uuid);
}
/** /**
* Saves the warp lists to the database * Saves the warp lists to the database
*/ */
@ -275,47 +296,44 @@ public class WarpSignsManager {
*/ */
@NonNull @NonNull
public SignCacheItem getSignInfo(@NonNull World world, @NonNull UUID uuid) { public SignCacheItem getSignInfo(@NonNull World world, @NonNull UUID uuid) {
List<String> result = new ArrayList<>();
//get the sign info //get the sign info
Location signLocation = getWarp(world, uuid); Location signLocation = getWarp(world, uuid);
if (signLocation != null && signLocation.getBlock().getType().name().contains("SIGN")) { if (signLocation == null || !signLocation.getBlock().getType().name().contains("SIGN")) {
Sign sign = (Sign)signLocation.getBlock().getState(); return new SignCacheItem();
result.addAll(Arrays.asList(sign.getLines()));
// Clean up - remove the [WELCOME] line
result.remove(0);
// Remove any trailing blank lines
result.removeIf(String::isEmpty);
// Set the initial color per lore setting
for (int i = 0; i< result.size(); i++) {
result.set(i, ChatColor.translateAlternateColorCodes('&', addon.getSettings().getLoreFormat()) + result.get(i));
}
// Get the sign type
String prefix = plugin.getIWM().getAddon(world).map(Addon::getPermissionPrefix).orElse("");
Material icon;
if (!prefix.isEmpty())
{
icon = Material.matchMaterial(
this.getPermissionValue(User.getInstance(uuid),
prefix + "island.warp",
this.addon.getSettings().getIcon()));
}
else
{
icon = Material.matchMaterial(this.addon.getSettings().getIcon());
}
if (icon == null || icon.name().contains("SIGN")) {
return new SignCacheItem(result, Material.valueOf(sign.getType().name().replace("WALL_", "")));
} else {
return new SignCacheItem(result, icon);
}
} else {
addon.getWarpSignsManager().removeWarp(world, uuid);
} }
return new SignCacheItem(Collections.emptyList(), Material.AIR); Sign sign = (Sign)signLocation.getBlock().getState();
List<String> result = new ArrayList<>(Arrays.asList(sign.getLines()));
// Clean up - remove the [WELCOME] line
result.remove(0);
// Remove any trailing blank lines
result.removeIf(String::isEmpty);
// Set the initial color per lore setting
for (int i = 0; i< result.size(); i++) {
result.set(i, ChatColor.translateAlternateColorCodes('&', addon.getSettings().getLoreFormat()) + result.get(i));
}
// Get the sign type
String prefix = plugin.getIWM().getAddon(world).map(Addon::getPermissionPrefix).orElse("");
Material icon;
if (!prefix.isEmpty())
{
icon = Material.matchMaterial(
this.getPermissionValue(Objects.requireNonNull(User.getInstance(uuid)),
prefix + "island.warp",
this.addon.getSettings().getIcon()));
}
else
{
icon = Material.matchMaterial(this.addon.getSettings().getIcon());
}
if (icon == null || icon.name().contains("SIGN")) {
return new SignCacheItem(result, Material.valueOf(sign.getType().name().replace("WALL_", "")));
}
return new SignCacheItem(result, icon);
} }
/** /**
@ -332,16 +350,16 @@ public class WarpSignsManager {
final Location actualWarp = new Location(inFront.getWorld(), inFront.getBlockX() + 0.5D, inFront.getBlockY(), final Location actualWarp = new Location(inFront.getWorld(), inFront.getBlockX() + 0.5D, inFront.getBlockY(),
inFront.getBlockZ() + 0.5D, yaw, 30F); inFront.getBlockZ() + 0.5D, yaw, 30F);
Util.teleportAsync(user.getPlayer(), actualWarp, TeleportCause.COMMAND); Util.teleportAsync(user.getPlayer(), actualWarp, TeleportCause.COMMAND);
User warpOwner = User.getInstance(signOwner); User warpOwner = Objects.requireNonNull(User.getInstance(signOwner));
// Hide invisible players // Hide invisible players
if (warpOwner.isOnline() && !warpOwner.getPlayer().canSee(user.getPlayer())) { if (warpOwner.isOnline() && !warpOwner.getPlayer().canSee(user.getPlayer())) {
return; return;
} }
if (pvp) { if (pvp) {
user.sendMessage("protection.flags.PVP_OVERWORLD.active"); user.sendMessage("protection.flags.PVP_OVERWORLD.enabled");
user.getWorld().playSound(user.getLocation(), Sound.ENTITY_ARROW_HIT, 1F, 1F); user.getWorld().playSound(Objects.requireNonNull(user.getLocation()), Sound.ENTITY_ARROW_HIT, 1F, 1F);
} else { } else {
user.getWorld().playSound(user.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 1F, 1F); user.getWorld().playSound(Objects.requireNonNull(user.getLocation()), Sound.ENTITY_BAT_TAKEOFF, 1F, 1F);
} }
if (!warpOwner.equals(user)) { if (!warpOwner.equals(user)) {
warpOwner.sendMessage("warps.player-warped", "[name]", user.getName()); warpOwner.sendMessage("warps.player-warped", "[name]", user.getName());
@ -376,7 +394,7 @@ public class WarpSignsManager {
boolean pvp = false; boolean pvp = false;
if (island != null) { if (island != null) {
// Check for PVP // Check for PVP
switch (warpSpot.getWorld().getEnvironment()) { switch (Objects.requireNonNull(warpSpot.getWorld()).getEnvironment()) {
case NETHER: case NETHER:
pvp = island.isAllowed(Flags.PVP_NETHER); pvp = island.isAllowed(Flags.PVP_NETHER);
break; break;
@ -426,10 +444,10 @@ public class WarpSignsManager {
final Location actualWarp = new Location(warpSpot.getWorld(), warpSpot.getBlockX() + 0.5D, warpSpot.getBlockY(), final Location actualWarp = new Location(warpSpot.getWorld(), warpSpot.getBlockX() + 0.5D, warpSpot.getBlockY(),
warpSpot.getBlockZ() + 0.5D); warpSpot.getBlockZ() + 0.5D);
if (pvp) { if (pvp) {
user.sendMessage("protection.flags.PVP_OVERWORLD.active"); user.sendMessage("protection.flags.PVP_OVERWORLD.enabled");
user.getWorld().playSound(user.getLocation(), Sound.ENTITY_ARROW_HIT, 1F, 1F); user.getWorld().playSound(Objects.requireNonNull(user.getLocation()), Sound.ENTITY_ARROW_HIT, 1F, 1F);
} else { } else {
user.getWorld().playSound(user.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 1F, 1F); user.getWorld().playSound(Objects.requireNonNull(user.getLocation()), Sound.ENTITY_BAT_TAKEOFF, 1F, 1F);
} }
Util.teleportAsync(user.getPlayer(), actualWarp, TeleportCause.COMMAND); Util.teleportAsync(user.getPlayer(), actualWarp, TeleportCause.COMMAND);
} }
@ -469,10 +487,10 @@ public class WarpSignsManager {
String permPrefix = permissionPrefix + "."; String permPrefix = permissionPrefix + ".";
List<String> permissions = user.getEffectivePermissions().stream(). List<String> permissions = user.getEffectivePermissions().stream()
map(PermissionAttachmentInfo::getPermission). .map(PermissionAttachmentInfo::getPermission)
filter(permission -> permission.startsWith(permPrefix)). .filter(permission -> permission.startsWith(permPrefix))
collect(Collectors.toList()); .toList();
for (String permission : permissions) for (String permission : permissions)
{ {

View File

@ -0,0 +1,12 @@
package world.bentobox.warps;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.addons.Pladdon;
public class WarpsPladdon extends Pladdon {
@Override
public Addon getAddon() {
return new Warp();
}
}

View File

@ -4,7 +4,6 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
import org.bukkit.World; import org.bukkit.World;
@ -20,7 +19,7 @@ import world.bentobox.warps.Warp;
*/ */
public class WarpCommand extends DelayedTeleportCommand { public class WarpCommand extends DelayedTeleportCommand {
private Warp addon; private final Warp addon;
public WarpCommand(Warp addon, CompositeCommand bsbIslandCmd) { public WarpCommand(Warp addon, CompositeCommand bsbIslandCmd) {
super(bsbIslandCmd, addon.getSettings().getWarpCommand()); super(bsbIslandCmd, addon.getSettings().getWarpCommand());
@ -81,7 +80,7 @@ public class WarpCommand extends DelayedTeleportCommand {
@Override @Override
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) { public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
World world = getWorld() == null ? user.getWorld() : getWorld(); World world = getWorld() == null ? user.getWorld() : getWorld();
return Optional.of(addon.getWarpSignsManager().listWarps(world).stream().map(getPlayers()::getName).collect(Collectors.toList())); return Optional.of(addon.getWarpSignsManager().listWarps(world).stream().map(getPlayers()::getName).toList());
} }

View File

@ -4,9 +4,9 @@ import java.util.List;
import org.bukkit.World; import org.bukkit.World;
import world.bentobox.warps.Warp;
import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.api.user.User;
import world.bentobox.warps.Warp;
/** /**
* Handles the warps command * Handles the warps command
@ -15,7 +15,7 @@ import world.bentobox.bentobox.api.user.User;
*/ */
public class WarpsCommand extends CompositeCommand { public class WarpsCommand extends CompositeCommand {
private Warp addon; private final Warp addon;
public WarpsCommand(Warp addon, CompositeCommand bsbIslandCmd) { public WarpsCommand(Warp addon, CompositeCommand bsbIslandCmd) {
super(bsbIslandCmd, addon.getSettings().getWarpsCommand()); super(bsbIslandCmd, addon.getSettings().getWarpsCommand());

View File

@ -18,13 +18,13 @@ import world.bentobox.warps.Warp;
public class WarpCreateEvent extends Event{ public class WarpCreateEvent extends Event{
private static final HandlerList handlers = new HandlerList(); private static final HandlerList handlers = new HandlerList();
private Location warpLoc; private final Location warpLoc;
private UUID creator; private final UUID creator;
/** /**
* @param plugin - BSkyBlock plugin objects * @param plugin - BSkyBlock plugin objects
* @param warpLoc * @param warpLoc warp location
* @param creator * @param creator UUID of creator
*/ */
public WarpCreateEvent(Warp plugin, Location warpLoc, UUID creator){ public WarpCreateEvent(Warp plugin, Location warpLoc, UUID creator){
this.warpLoc = warpLoc; this.warpLoc = warpLoc;

View File

@ -40,7 +40,7 @@ public class WarpInitiateEvent extends Event implements Cancellable {
/** /**
* Set a different location to where the player will go * Set a different location to where the player will go
* @param warpLoc * @param warpLoc warp location
*/ */
public void setWarpLoc(Location warpLoc) { public void setWarpLoc(Location warpLoc) {
this.warpLoc = warpLoc; this.warpLoc = warpLoc;

View File

@ -1,75 +0,0 @@
/*******************************************************************************
* This file is part of ASkyBlock.
*
* ASkyBlock is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ASkyBlock is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ASkyBlock. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package world.bentobox.warps.event;
import java.util.List;
import java.util.UUID;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import world.bentobox.warps.Warp;
/**
* This event is fired when request is made for a sorted list of warps or when
* the API updateWarpPanel method is called.
* A listener to this event can reorder or rewrite the warp list by using setWarps.
* This new order will then be used in the warp panel.
*
* @author tastybento
*
*/
public class WarpListEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private List<UUID> warps;
/**
* @param plugin - BSkyBlock plugin objects
* @param warps
*/
public WarpListEvent(Warp plugin, List<UUID> warps) {
this.warps = warps;
}
/**
*The warp list is a collection of player UUID's and the default order is
* that players with the most recent login will be first.
* @return the warps
*/
public List<UUID> getWarps() {
return warps;
}
/**
* @param warps the warps to set
*/
public void setWarps(List<UUID> warps) {
this.warps = warps;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -5,8 +5,8 @@ import java.util.UUID;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import org.eclipse.jdt.annotation.NonNull;
import world.bentobox.warps.Warp; import org.eclipse.jdt.annotation.Nullable;
/** /**
* This event is fired when a Warp is removed (when a warp sign is broken) * This event is fired when a Warp is removed (when a warp sign is broken)
@ -18,32 +18,48 @@ import world.bentobox.warps.Warp;
public class WarpRemoveEvent extends Event{ public class WarpRemoveEvent extends Event{
private static final HandlerList handlers = new HandlerList(); private static final HandlerList handlers = new HandlerList();
private Location warpLoc; private final Location warpLoc;
private UUID remover; private final UUID remover;
private final UUID owner;
/** /**
* @param plugin - BSkyBlock plugin objects * @param warpLoc - Warp location
* @param warpLoc * @param remover - UUID of remover
* @param remover * @param owner - UUID of warp owner - rarely, may be null
*/ */
public WarpRemoveEvent(Warp plugin, Location warpLoc, UUID remover){ public WarpRemoveEvent(@NonNull Location warpLoc, UUID remover, @Nullable UUID owner){
this.warpLoc = warpLoc; this.warpLoc = warpLoc;
this.remover = remover; this.remover = remover;
this.owner = owner;
} }
/** /**
* Get the location of the removed Warp * Get the location of the removed Warp
* @return removed warp's location * @return removed warp's location
*/ */
public Location getWarpLocation(){return this.warpLoc;} @NonNull
public Location getWarpLocation(){
return this.warpLoc;
}
/** /**
* Get who has removed the warp * Get who has removed the warp
* @return the warp's remover * @return the warp's remover
*/ */
public UUID getRemover(){return this.remover;} @NonNull
public UUID getRemover(){
return this.remover;
}
@Override /**
* @return the owner
*/
@Nullable
protected UUID getOwner() {
return owner;
}
@Override
public HandlerList getHandlers() { public HandlerList getHandlers() {
return handlers; return handlers;
} }

View File

@ -3,9 +3,14 @@ package world.bentobox.warps.listeners;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import org.bukkit.*; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Tag;
import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.Sign; import org.bukkit.block.Sign;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -14,9 +19,10 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.SignChangeEvent; import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.events.addon.AddonEvent; import world.bentobox.bentobox.api.events.addon.AddonEvent;
import world.bentobox.bentobox.api.events.team.TeamKickEvent; import world.bentobox.bentobox.api.events.team.TeamKickEvent;
@ -34,9 +40,11 @@ import world.bentobox.warps.event.WarpRemoveEvent;
*/ */
public class WarpSignsListener implements Listener { public class WarpSignsListener implements Listener {
private BentoBox plugin; private static final String WARPS_DEACTIVATE = "warps.deactivate";
private Warp addon; private final BentoBox plugin;
private final Warp addon;
/** /**
* @param addon - addon * @param addon - addon
@ -79,14 +87,14 @@ public class WarpSignsListener implements Listener {
public void onPlayerLeave(TeamLeaveEvent e) { public void onPlayerLeave(TeamLeaveEvent e) {
// Remove any warp signs from this game mode // Remove any warp signs from this game mode
addon.getWarpSignsManager().removeWarp(e.getIsland().getWorld(), e.getPlayerUUID()); addon.getWarpSignsManager().removeWarp(e.getIsland().getWorld(), e.getPlayerUUID());
User.getInstance(e.getPlayerUUID()).sendMessage("warps.deactivate"); Objects.requireNonNull(User.getInstance(e.getPlayerUUID())).sendMessage(WARPS_DEACTIVATE);
} }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerLeave(TeamKickEvent e) { public void onPlayerLeave(TeamKickEvent e) {
// Remove any warp signs from this game mode // Remove any warp signs from this game mode
addon.getWarpSignsManager().removeWarp(e.getIsland().getWorld(), e.getPlayerUUID()); addon.getWarpSignsManager().removeWarp(e.getIsland().getWorld(), e.getPlayerUUID());
User.getInstance(e.getPlayerUUID()).sendMessage("warps.deactivate"); Objects.requireNonNull(User.getInstance(e.getPlayerUUID())).sendMessage(WARPS_DEACTIVATE);
} }
/** /**
@ -99,21 +107,22 @@ public class WarpSignsListener implements Listener {
boolean inWorld = addon.getPlugin().getIWM().inWorld(b.getWorld()); boolean inWorld = addon.getPlugin().getIWM().inWorld(b.getWorld());
// Signs only // Signs only
// FIXME: When we drop support for 1.13, switch to Tag.SIGNS // FIXME: When we drop support for 1.13, switch to Tag.SIGNS
if (!e.getBlock().getType().name().contains("SIGN") if (!b.getType().name().contains("SIGN")
|| (inWorld && !addon.inRegisteredWorld(b.getWorld())) || (inWorld && !addon.inRegisteredWorld(b.getWorld()))
|| (!inWorld && !addon.getSettings().isAllowInOtherWorlds()) ) { || (!inWorld && !addon.getSettings().isAllowInOtherWorlds())
|| !isWarpSign(b)) {
return; return;
} }
User user = User.getInstance(e.getPlayer()); User user = User.getInstance(e.getPlayer());
if (isWarpSign(b)) { if (user == null) return;
if (isPlayersSign(e.getPlayer(), b, inWorld)) { UUID owner = addon.getWarpSignsManager().getWarpOwnerUUID(b.getLocation()).orElse(null);
addon.getWarpSignsManager().removeWarp(b.getLocation()); if (isPlayersSign(e.getPlayer(), b, inWorld)) {
Bukkit.getPluginManager().callEvent(new WarpRemoveEvent(addon, b.getLocation(), user.getUniqueId())); addon.getWarpSignsManager().removeWarp(b.getLocation());
} else { Bukkit.getPluginManager().callEvent(new WarpRemoveEvent(b.getLocation(), user.getUniqueId(), owner));
// Someone else's sign - not allowed } else {
user.sendMessage("warps.error.no-remove"); // Someone else's sign - not allowed
e.setCancelled(true); user.sendMessage("warps.error.no-remove");
} e.setCancelled(true);
} }
} }
@ -144,9 +153,9 @@ public class WarpSignsListener implements Listener {
return; return;
} }
String title = e.getLine(0); String title = e.getLine(0);
User user = User.getInstance(e.getPlayer()); User user = Objects.requireNonNull(User.getInstance(e.getPlayer()));
// Check if someone is changing their own sign // Check if someone is changing their own sign
if (title.equalsIgnoreCase(addon.getSettings().getWelcomeLine())) { if (title != null && title.equalsIgnoreCase(addon.getSettings().getWelcomeLine())) {
// Welcome sign detected - check permissions // Welcome sign detected - check permissions
if (noPerms(user, b.getWorld(), inWorld)) { if (noPerms(user, b.getWorld(), inWorld)) {
return; return;
@ -157,11 +166,7 @@ public class WarpSignsListener implements Listener {
} }
// Check if the player already has a sign // Check if the player already has a sign
final Location oldSignLoc = addon.getWarpSignsManager().getWarp(b.getWorld(), user.getUniqueId()); final Location oldSignLoc = addon.getWarpSignsManager().getWarp(b.getWorld(), user.getUniqueId());
if (oldSignLoc == null) { if (oldSignLoc != null) {
// First time the sign has been placed or this is a new
// sign
addSign(e, user, b);
} else {
// A sign already exists. Check if it still there and if // A sign already exists. Check if it still there and if
// so, // so,
// deactivate it // deactivate it
@ -173,14 +178,16 @@ public class WarpSignsListener implements Listener {
if (oldSign.getLine(0).equalsIgnoreCase(ChatColor.GREEN + addon.getSettings().getWelcomeLine())) { if (oldSign.getLine(0).equalsIgnoreCase(ChatColor.GREEN + addon.getSettings().getWelcomeLine())) {
oldSign.setLine(0, ChatColor.RED + addon.getSettings().getWelcomeLine()); oldSign.setLine(0, ChatColor.RED + addon.getSettings().getWelcomeLine());
oldSign.update(true, false); oldSign.update(true, false);
user.sendMessage("warps.deactivate"); user.sendMessage(WARPS_DEACTIVATE);
addon.getWarpSignsManager().removeWarp(oldSignBlock.getWorld(), user.getUniqueId()); addon.getWarpSignsManager().removeWarp(oldSignBlock.getWorld(), user.getUniqueId());
Bukkit.getPluginManager().callEvent(new WarpRemoveEvent(addon, oldSign.getLocation(), user.getUniqueId())); @Nullable
UUID owner = addon.getWarpSignsManager().getWarpOwnerUUID(oldSignLoc).orElse(null);
Bukkit.getPluginManager().callEvent(new WarpRemoveEvent(oldSign.getLocation(), user.getUniqueId(), owner));
} }
} }
// Set up the new warp sign // Set up the new warp sign
addSign(e, user, b);
} }
addSign(e, user, b);
} }
} }
@ -226,7 +233,10 @@ public class WarpSignsListener implements Listener {
user.sendMessage("warps.success"); user.sendMessage("warps.success");
e.setLine(0, ChatColor.GREEN + addon.getSettings().getWelcomeLine()); e.setLine(0, ChatColor.GREEN + addon.getSettings().getWelcomeLine());
for (int i = 1; i<4; i++) { for (int i = 1; i<4; i++) {
e.setLine(i, ChatColor.translateAlternateColorCodes('&', e.getLine(i))); String line = e.getLine(i);
if (line != null) {
e.setLine(i, ChatColor.translateAlternateColorCodes('&', line));
}
} }
Map<String, Object> keyValues = new HashMap<>(); Map<String, Object> keyValues = new HashMap<>();

View File

@ -46,10 +46,11 @@ public class WarpsData implements DataObject {
/** /**
* Puts all the data from the map into this objects ready for saving * Puts all the data from the map into this objects ready for saving
* @param worldsWarpList * @param worldsWarpList 2D map of warp locations by world vs UUID
* @return this class filled with data * @return this class filled with data
*/ */
public WarpsData save(Map<World, Map<UUID, Location>> worldsWarpList) { public WarpsData save(Map<World, Map<UUID, Location>> worldsWarpList) {
getWarpSigns().clear();
worldsWarpList.values().forEach(world -> world.forEach((uuid,location) -> warpSigns.put(location, uuid))); worldsWarpList.values().forEach(world -> world.forEach((uuid,location) -> warpSigns.put(location, uuid)));
return this; return this;
} }

View File

@ -2,7 +2,7 @@ name: Warps
main: world.bentobox.warps.Warp main: world.bentobox.warps.Warp
version: ${version}${build.number} version: ${version}${build.number}
icon: OAK_SIGN icon: OAK_SIGN
api-version: 1.15.4 api-version: 1.17
authors: tastybento authors: tastybento

View File

@ -26,11 +26,11 @@ disabled-gamemodes: []
# #
# Warp panel name formatting. # Warp panel name formatting.
# Example: &c will make names red, &f is white # Example: &c will make names red, &f is white
name-format: &f name-format: "&f"
# #
# Warp panel default lore formatting. # Warp panel default lore formatting.
# Example: &c will make lore red. &f is white # Example: &c will make lore red. &f is white
lore-format: &f lore-format: "&f"
# #
# Allow random teleport - adds a button to the warp panel that goes to a random warp sign # Allow random teleport - adds a button to the warp panel that goes to a random warp sign
random-allowed: true random-allowed: true

View File

@ -0,0 +1,29 @@
#
# This is a YML file. Be careful when editing. Check your edits in a YAML checker like #
# the one at http://yaml-online-parser.appspot.com #
warp:
help:
description: đi đến điểm dịch chuyển của người chơi
parameters: <tên người chơi>
warps:
deactivate: '&cBảng cũ đã vô hiệu hóa!'
error:
does-not-exist: '&cUầy! Điểm dịch chuyển đó không tồn tại!'
no-permission: '&cBạn không có quyền làm điều đó!'
no-remove: '&cBạn không thể xóa bảng đó!'
no-warps-yet: '&cChưa có điểm dịch chuyển nào'
not-enough-level: '&cCấp đảo của bạn không đủ cao!'
not-on-island: '&cBạn phải ở đảo của bạn để làm điều đó!'
not-safe: '&cĐiểm dịch chuyển không an toàn!'
your-level-is: '&cCấp đảo của bạn là [level] và phải cao hơn [required]. Hãy dùng lệnh xem cấp đảo.'
help:
description: mở bảng dịch chuyển
next: '&6Trang kế'
player-warped: '&2[name] đã vào điểm dịch chuyển của bạn!'
previous: '&6Trang trước'
random: '&4Điểm dịch chuyển ngẫu nhiên'
sign-removed: '&cĐã xóa bảng dịch chuyển!'
success: '&aThành công!'
title: Bảng Dịch Chuyển
warpTip: '&6Đặt bảng với dòng chữ [text] ở dòng đầu tiên'
warpToPlayersSign: '&6Đang dịch chuyển đến chỗ của [player]'

View File

@ -0,0 +1,8 @@
name: Warps
main: world.bentobox.warps.WarpsPladdon
version: ${version}
api-version: 1.17
description: A Warp Pladdon for BentoBox
author: tastybento
depend:
- BentoBox

View File

@ -5,6 +5,8 @@ import static org.junit.Assert.assertFalse;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -12,6 +14,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
@ -21,22 +24,21 @@ import org.bukkit.block.Block;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFactory; import org.bukkit.inventory.ItemFactory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.scheduler.BukkitScheduler;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer; import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito; import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.modules.junit4.PowerMockRunner;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.AbstractDatabaseHandler; import world.bentobox.bentobox.database.AbstractDatabaseHandler;
import world.bentobox.bentobox.database.DatabaseSetup; import world.bentobox.bentobox.database.DatabaseSetup;
@ -63,11 +65,16 @@ public class WarpPanelManagerTest {
private World world; private World world;
@Mock @Mock
private Inventory top; private Inventory top;
private UUID uuid;
@Mock @Mock
private Settings settings; private Settings settings;
@Mock @Mock
private static AbstractDatabaseHandler<Object> handler; private static AbstractDatabaseHandler<Object> handler;
@Mock
private BukkitScheduler scheduler;
private List<UUID> list;
// Class under test
private WarpPanelManager wpm;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@BeforeClass @BeforeClass
@ -82,30 +89,24 @@ public class WarpPanelManagerTest {
} }
/** /**
* @throws java.lang.Exception
*/ */
@Before @Before
public void setUp() throws Exception { public void setUp() {
when(addon.getWarpSignsManager()).thenReturn(wsm); when(addon.getWarpSignsManager()).thenReturn(wsm);
// Fill with 200 fake warps (I'm banking on them all being different, but there could be a clash) // Fill with 200 fake warps (I'm banking on them all being different, but there could be a clash)
List<UUID> list = new ArrayList<>(); list = new ArrayList<>();
for (int i = 0; i< 200; i++) { for (int i = 0; i< 200; i++) {
list.add(UUID.randomUUID()); list.add(UUID.randomUUID());
} }
// One final one // One final one
uuid = UUID.randomUUID(); UUID uuid = UUID.randomUUID();
list.add(uuid); list.add(uuid);
when(wsm.getSortedWarps(any())).thenReturn(list); when(wsm.getSortedWarps(any())).thenReturn(CompletableFuture.completedFuture(list));
// User and player // User and player
when(user.getPlayer()).thenReturn(player); when(user.getPlayer()).thenReturn(player);
when(user.getTranslation(Mockito.any())).thenAnswer(new Answer<String>() { when(user.getTranslation(any())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class));
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
return invocation.getArgument(0, String.class);
}});
// BentoBox // BentoBox
@ -116,125 +117,55 @@ public class WarpPanelManagerTest {
when(addon.getPlugin()).thenReturn(plugin); when(addon.getPlugin()).thenReturn(plugin);
// Bukkit // Bukkit
PowerMockito.mockStatic(Bukkit.class); PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
ItemFactory itemF = mock(ItemFactory.class); ItemFactory itemF = mock(ItemFactory.class);
ItemMeta imeta = mock(ItemMeta.class); ItemMeta imeta = mock(ItemMeta.class);
when(itemF.getItemMeta(any())).thenReturn(imeta); when(itemF.getItemMeta(any())).thenReturn(imeta);
when(Bukkit.getItemFactory()).thenReturn(itemF); when(Bukkit.getItemFactory()).thenReturn(itemF);
when(Bukkit.getScheduler()).thenReturn(scheduler);
// Inventory // Inventory
when(top.getSize()).thenReturn(9); when(top.getSize()).thenReturn(9);
when(Bukkit.createInventory(any(), Mockito.anyInt(), any())).thenReturn(top); when(Bukkit.createInventory(any(), anyInt(), any())).thenReturn(top);
when(settings.getIcon()).thenReturn("SIGN"); when(settings.getIcon()).thenReturn("SIGN");
when(addon.getSettings()).thenReturn(settings); when(addon.getSettings()).thenReturn(settings);
Location location = mock(Location.class); Location location = mock(Location.class);
Block block = mock(Block.class); Block block = mock(Block.class);
Material sign_type; Material signType;
try { try {
sign_type = Material.valueOf("SIGN"); signType = Material.valueOf("SIGN");
} catch (Exception e) { } catch (Exception e) {
sign_type = Material.valueOf("OAK_SIGN"); signType = Material.valueOf("OAK_SIGN");
} }
when(block.getType()).thenReturn(sign_type); when(block.getType()).thenReturn(signType);
when(location.getBlock()).thenReturn(block); when(location.getBlock()).thenReturn(block);
// Sign block // Sign block
when(wsm.getWarp(any(), any())).thenReturn(location); when(wsm.getWarp(any(), any())).thenReturn(location);
// Sign cache // Sign cache
SignCacheItem sc = mock(SignCacheItem.class);
when(sc.getSignText()).thenReturn(Collections.singletonList("[welcome]")); SignCacheItem sc = new SignCacheItem(Collections.singletonList("[welcome]"), signType);
when(sc.getType()).thenReturn(sign_type);
when(wsm.getSignInfo(any(), any())).thenReturn(sc); when(wsm.getSignInfo(any(), any())).thenReturn(sc);
// Class under test
wpm = new WarpPanelManager(addon);
} }
/** /**
* Test method for {@link WarpPanelManager#showWarpPanel(org.bukkit.World, world.bentobox.bbox.api.user.User, int)}. * Test method for {@link WarpPanelManager#processSigns(CompletableFuture, PanelBuilder, User, int, World)}.
*/
@Test
public void testShowWarpPanelFirst() {
ArgumentCaptor<ItemStack> argument = ArgumentCaptor.forClass(ItemStack.class);
WarpPanelManager wpm = new WarpPanelManager(addon);
wpm.showWarpPanel(world, user, 0);
verify(player).openInventory(Mockito.eq(top));
// Just next sign
verify(top, Mockito.times(53)).setItem(Mockito.anyInt(),argument.capture());
assertEquals(Material.STONE, argument.getAllValues().get(52).getType());
}
/**
* Test method for {@link WarpPanelManager#showWarpPanel(org.bukkit.World, world.bentobox.bbox.api.user.User, int)}.
*/
@Test
public void testShowWarpPanelFirstRandom() {
when(settings.isRandomAllowed()).thenReturn(true);
ArgumentCaptor<ItemStack> argument = ArgumentCaptor.forClass(ItemStack.class);
WarpPanelManager wpm = new WarpPanelManager(addon);
wpm.showWarpPanel(world, user, 0);
verify(player).openInventory(Mockito.eq(top));
// Check crystal
verify(top, Mockito.atLeastOnce()).setItem(anyInt(), argument.capture());
assertEquals(Material.END_CRYSTAL, argument.getAllValues().get(0).getType());
}
/**
* Test method for {@link WarpPanelManager#showWarpPanel(org.bukkit.World, world.bentobox.bbox.api.user.User, int)}.
*/
@Test
public void testShowWarpPanelNoRandom() {
when(settings.isRandomAllowed()).thenReturn(false);
ArgumentCaptor<ItemStack> argument = ArgumentCaptor.forClass(ItemStack.class);
WarpPanelManager wpm = new WarpPanelManager(addon);
wpm.showWarpPanel(world, user, 0);
verify(player).openInventory(Mockito.eq(top));
// Check crystal
verify(top, Mockito.atLeastOnce()).setItem(anyInt(), argument.capture());
assertFalse(argument.getAllValues().get(0).getType().equals(Material.END_CRYSTAL));
}
/**
* Test method for {@link WarpPanelManager#showWarpPanel(org.bukkit.World, world.bentobox.bbox.api.user.User, int)}.
*/
@Test
public void testShowWarpPanelMiddle() {
ArgumentCaptor<ItemStack> argument = ArgumentCaptor.forClass(ItemStack.class);
WarpPanelManager wpm = new WarpPanelManager(addon);
wpm.showWarpPanel(world, user, 1);
verify(player).openInventory(Mockito.eq(top));
// includes previous and next signs
verify(top, Mockito.times(54)).setItem(Mockito.anyInt(), argument.capture());
assertEquals(Material.STONE, argument.getAllValues().get(52).getType());
assertEquals(Material.COBBLESTONE, argument.getAllValues().get(53).getType());
}
/**
* Test method for {@link WarpPanelManager#showWarpPanel(org.bukkit.World, world.bentobox.bbox.api.user.User, int)}.
*/
@Test
public void testShowWarpPanelLast() {
ArgumentCaptor<ItemStack> argument = ArgumentCaptor.forClass(ItemStack.class);
WarpPanelManager wpm = new WarpPanelManager(addon);
wpm.showWarpPanel(world, user, 3);
verify(player).openInventory(Mockito.eq(top));
// Final amount, just previous sign
verify(top, Mockito.times(46)).setItem(Mockito.anyInt(), argument.capture());
assertEquals(Material.COBBLESTONE, argument.getAllValues().get(45).getType());
}
/**
* Test method for {@link WarpPanelManager#showWarpPanel(org.bukkit.World, world.bentobox.bbox.api.user.User, int)}.
*/ */
@Test @Test
public void testShowWarpPanelTestCache() { public void testShowWarpPanelTestCache() {
WarpPanelManager wpm = new WarpPanelManager(addon); PanelBuilder pb = mock(PanelBuilder.class);
// Do 45 initial lookups of sign text // Do initial lookups of sign text
wpm.showWarpPanel(world, user, 3); wpm.processSigns(new CompletableFuture<>(), pb, user, 3, world);
// Get the panel again // Get the panel again
wpm.showWarpPanel(world, user, 3); wpm.processSigns(new CompletableFuture<>(), pb, user, 3, world);
// Should only check this 45 times because the sign text is cached // Should only check this 201 times in total because the sign text is cached
verify(wsm, Mockito.times(45)).getSignInfo(any(), any()); verify(wsm, times(201)).getSignInfo(any(), any());
} }
@ -243,14 +174,156 @@ public class WarpPanelManagerTest {
*/ */
@Test @Test
public void testRemoveWarp() { public void testRemoveWarp() {
WarpPanelManager wpm = new WarpPanelManager(addon); assertFalse(wpm.removeWarp(world, UUID.randomUUID()));
wpm.showWarpPanel(world, user, 3); }
wpm.showWarpPanel(world, user, 3);
wpm.removeWarp(world, uuid); /**
wpm.showWarpPanel(world, user, 3); * Test method for {@link WarpPanelManager#buildPanel(PanelBuilder, User, int, World)}
// Removing the UUID should force a refresh and therefore 46 lookups */
verify(wsm, Mockito.times(46)).getSignInfo(any(), any()); @Test
public void testBuildPanel() {
PanelBuilder pb = mock(PanelBuilder.class);
wpm.buildPanel(pb, user, 3, world);
// Removing the UUID should force a refresh and therefore 201 lookups
verify(wsm, times(201)).getSignInfo(any(), any());
} }
/**
* Test method for {@link WarpPanelManager#addNavigation(PanelBuilder, User, World, int, int, int)}
*/
@Test
public void testAddNavigationNoNav() {
PanelBuilder pb = mock(PanelBuilder.class);
wpm.addNavigation(pb, user, world, 0, 0, 0);
verify(pb, never()).item(any());
}
/**
* Test method for {@link WarpPanelManager#addNavigation(PanelBuilder, User, World, int, int, int)}
*/
@Test
public void testAddNavigationNoNavNext() {
PanelBuilder pb = mock(PanelBuilder.class);
wpm.addNavigation(pb, user, world, 0, 0, 100);
verify(pb).item(any());
verify(user).getTranslation("warps.next");
}
/**
* Test method for {@link WarpPanelManager#addNavigation(PanelBuilder, User, World, int, int, int)}
*/
@Test
public void testAddNavigationNoNavPrev() {
PanelBuilder pb = mock(PanelBuilder.class);
wpm.addNavigation(pb, user, world, 60, 2, 20);
verify(pb).item(any());
verify(user).getTranslation("warps.previous");
}
/**
* Test method for {@link WarpPanelManager#addNavigation(PanelBuilder, User, World, int, int, int)}
*/
@Test
public void testAddNavigationNoNavNextAndPrev() {
PanelBuilder pb = mock(PanelBuilder.class);
wpm.addNavigation(pb, user, world, 60, 2, 100);
verify(pb, times(2)).item(any());
verify(user).getTranslation("warps.previous");
verify(user).getTranslation("warps.next");
}
private int mainBod(int page, int j, boolean random) {
when(settings.isRandomAllowed()).thenReturn(random);
PanelBuilder pb = mock(PanelBuilder.class);
int r = wpm.buildMainBody(pb, user, page, world, list);
verify(pb, times(j)).item(any());
if (random && page <= 0) {
verify(user).getTranslation("warps.random");
} else {
verify(user, never()).getTranslation("warps.random");
}
return r;
}
/**
* Test method for {@link WarpPanelManager#buildMainBody(PanelBuilder, User, int, World, List, boolean)}
*/
@Test
public void testBuildMainBodyNoRandomPage0() {
assertEquals(201, mainBod(0, 201, false));
}
/**
* Test method for {@link WarpPanelManager#buildMainBody(PanelBuilder, User, int, World, List, boolean)}
*/
@Test
public void testBuildMainBodyNoRandomPage1() {
assertEquals(201, mainBod(1, 149, false));
}
/**
* Test method for {@link WarpPanelManager#buildMainBody(PanelBuilder, User, int, World, List, boolean)}
*/
@Test
public void testBuildMainBodyNoRandomPage2() {
assertEquals(201, mainBod(2, 97, false));
}
/**
* Test method for {@link WarpPanelManager#buildMainBody(PanelBuilder, User, int, World, List, boolean)}
*/
@Test
public void testBuildMainBodyNoRandomPage3() {
assertEquals(201, mainBod(3, 45, false));
}
/**
* Test method for {@link WarpPanelManager#buildMainBody(PanelBuilder, User, int, World, List, boolean)}
*/
@Test
public void testBuildMainBodyNoRandomPageMinus1() {
assertEquals(201, mainBod(-1, 201, false));
}
/**
* Test method for {@link WarpPanelManager#buildMainBody(PanelBuilder, User, int, World, List, boolean)}
*/
@Test
public void testBuildMainBodyRandomPage0() {
assertEquals(201, mainBod(0, 201, true));
}
/**
* Test method for {@link WarpPanelManager#buildMainBody(PanelBuilder, User, int, World, List, boolean)}
*/
@Test
public void testBuildMainBodyRandomPage1() {
assertEquals(201, mainBod(1, 149, true));
}
/**
* Test method for {@link WarpPanelManager#buildMainBody(PanelBuilder, User, int, World, List, boolean)}
*/
@Test
public void testBuildMainBodyRandomPage2() {
assertEquals(201, mainBod(2, 97, true));
}
/**
* Test method for {@link WarpPanelManager#buildMainBody(PanelBuilder, User, int, World, List, boolean)}
*/
@Test
public void testBuildMainBodyRandomPage3() {
assertEquals(201, mainBod(3, 45, true));
}
/**
* Test method for {@link WarpPanelManager#buildMainBody(PanelBuilder, User, int, World, List, boolean)}
*/
@Test
public void testBuildMainBodyRandomPageMinus1() {
assertEquals(201, mainBod(-1, 201, true));
}
} }

View File

@ -13,14 +13,20 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.bukkit.*; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.World.Environment; import org.bukkit.World.Environment;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
@ -80,7 +86,7 @@ public class WarpSignsManagerTest {
private Logger logger; private Logger logger;
@Mock @Mock
private WarpsData load; private WarpsData load;
private UUID uuid = UUID.randomUUID(); private final UUID uuid = UUID.randomUUID();
@Mock @Mock
private Location location; private Location location;
@Mock @Mock
@ -120,7 +126,7 @@ public class WarpSignsManagerTest {
} }
/** /**
* @throws java.lang.Exception * @throws java.lang.Exception exception
*/ */
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
@ -158,6 +164,7 @@ public class WarpSignsManagerTest {
when(location.getBlockX()).thenReturn(23); when(location.getBlockX()).thenReturn(23);
when(location.getBlockY()).thenReturn(24); when(location.getBlockY()).thenReturn(24);
when(location.getBlockZ()).thenReturn(25); when(location.getBlockZ()).thenReturn(25);
when(player.getLocation()).thenReturn(location);
when(world.getEnvironment()).thenReturn(Environment.NORMAL); when(world.getEnvironment()).thenReturn(Environment.NORMAL);
when(world.isChunkLoaded(anyInt(), anyInt())).thenReturn(true); when(world.isChunkLoaded(anyInt(), anyInt())).thenReturn(true);
@ -176,7 +183,7 @@ public class WarpSignsManagerTest {
when(block.getRelative(any())).thenReturn(block); when(block.getRelative(any())).thenReturn(block);
// Handler // Handler
when(handler.objectExists(eq("warps"))).thenReturn(true); when(handler.objectExists("warps")).thenReturn(true);
Map<Location, UUID> warpMap = Collections.singletonMap(location, uuid); Map<Location, UUID> warpMap = Collections.singletonMap(location, uuid);
when(load.getWarpSigns()).thenReturn(warpMap); when(load.getWarpSigns()).thenReturn(warpMap);
when(handler.loadObject(anyString())).thenReturn(load); when(handler.loadObject(anyString())).thenReturn(load);
@ -187,13 +194,13 @@ public class WarpSignsManagerTest {
when(settings.getLoreFormat()).thenReturn("&f"); when(settings.getLoreFormat()).thenReturn("&f");
when(settings.getIcon()).thenReturn("SIGN"); when(settings.getIcon()).thenReturn("SIGN");
// Bukkit // Bukkit
PowerMockito.mockStatic(Bukkit.class); PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
when(Bukkit.getPluginManager()).thenReturn(pim); when(Bukkit.getPluginManager()).thenReturn(pim);
// Players Manager // Players Manager
when(plugin.getPlayers()).thenReturn(pm); when(plugin.getPlayers()).thenReturn(pm);
when(pm.getName(eq(uuid))).thenReturn("tastybento"); when(pm.getName(uuid)).thenReturn("tastybento");
// Offline player // Offline player
when(server.getOfflinePlayer(any(UUID.class))).thenReturn(offlinePlayer); when(server.getOfflinePlayer(any(UUID.class))).thenReturn(offlinePlayer);
@ -215,10 +222,9 @@ public class WarpSignsManagerTest {
} }
/** /**
* @throws java.lang.Exception
*/ */
@After @After
public void tearDown() throws Exception { public void tearDown() {
User.clearUsers(); User.clearUsers();
} }
@ -263,7 +269,7 @@ public class WarpSignsManagerTest {
/** /**
* Test method for {@link world.bentobox.warps.WarpSignsManager#getWarpMap(org.bukkit.World)}. * Test method for {@link world.bentobox.warps.WarpSignsManager#getWarpMap(org.bukkit.World)}.
* @throws Exception * @throws Exception exception
*/ */
@Test @Test
public void testGetWarpMapNullDatabaseObject() throws Exception { public void testGetWarpMapNullDatabaseObject() throws Exception {
@ -277,17 +283,16 @@ public class WarpSignsManagerTest {
*/ */
@Test @Test
public void testGetWarpMapNothingInDatabase() { public void testGetWarpMapNothingInDatabase() {
when(handler.objectExists(eq("warps"))).thenReturn(false); when(handler.objectExists("warps")).thenReturn(false);
wsm = new WarpSignsManager(addon, plugin); wsm = new WarpSignsManager(addon, plugin);
assertTrue("Map is not empty", wsm.getWarpMap(world).isEmpty()); assertTrue("Map is not empty", wsm.getWarpMap(world).isEmpty());
} }
/** /**
* Test method for {@link world.bentobox.warps.WarpSignsManager#WarpSignsManager(world.bentobox.warps.Warp, world.bentobox.bentobox.BentoBox)}. * Test method for {@link world.bentobox.warps.WarpSignsManager#WarpSignsManager(world.bentobox.warps.Warp, world.bentobox.bentobox.BentoBox)}.
* @throws Exception
*/ */
@Test @Test
public void testWarpSignsManager() throws Exception { public void testWarpSignsManager() {
verify(addon).log("Loading warps..."); verify(addon).log("Loading warps...");
verify(load).getWarpSigns(); verify(load).getWarpSigns();
verify(block).getType(); verify(block).getType();
@ -358,7 +363,7 @@ public class WarpSignsManagerTest {
*/ */
@Test @Test
public void testGetWarpOwner() { public void testGetWarpOwner() {
assertEquals("tastybento", wsm.getWarpOwner(location)); assertEquals("tastybento", wsm.getWarpOwner(location));
} }
/** /**
@ -366,7 +371,8 @@ public class WarpSignsManagerTest {
*/ */
@Test @Test
public void testGetSortedWarps() { public void testGetSortedWarps() {
assertEquals(1, wsm.getSortedWarps(world).size()); CompletableFuture<List<UUID>> r = new CompletableFuture<>();
assertEquals(1, wsm.processWarpMap(r, world).size());
} }
/** /**
@ -398,9 +404,7 @@ public class WarpSignsManagerTest {
/** /**
* Test method for {@link world.bentobox.warps.WarpSignsManager#saveWarpList()}. * Test method for {@link world.bentobox.warps.WarpSignsManager#saveWarpList()}.
* @throws IntrospectionException * @throws Exception general exception
* @throws InvocationTargetException
* @throws Exception
*/ */
@Test @Test
public void testSaveWarpList() throws Exception { public void testSaveWarpList() throws Exception {
@ -426,6 +430,7 @@ public class WarpSignsManagerTest {
when(p.getUniqueId()).thenReturn(UUID.randomUUID()); when(p.getUniqueId()).thenReturn(UUID.randomUUID());
when(p.getWorld()).thenReturn(world); when(p.getWorld()).thenReturn(world);
when(p.getName()).thenReturn("tastybento"); when(p.getName()).thenReturn("tastybento");
when(p.getLocation()).thenReturn(location);
@Nullable @Nullable
User u = User.getInstance(p); User u = User.getInstance(p);
wsm.warpPlayer(world, u, uuid); wsm.warpPlayer(world, u, uuid);
@ -455,13 +460,13 @@ public class WarpSignsManagerTest {
// Save // Save
wsm.saveWarpList(); wsm.saveWarpList();
// Default load in constructor check // Default load in constructor check
verify(addon, times(2)).log(eq("Loading warps...")); verify(addon, times(2)).log("Loading warps...");
assertTrue(wsm.getWarpMap(world).isEmpty()); assertTrue(wsm.getWarpMap(world).isEmpty());
} }
/** /**
* Test method for {@link world.bentobox.warps.WarpSignsManager#loadWarpList()}. * Test method for {@link world.bentobox.warps.WarpSignsManager#loadWarpList()}.
* @throws Exception * @throws Exception exception
*/ */
@Test @Test
public void testLoadWarpListEmptyWarpTable() throws Exception { public void testLoadWarpListEmptyWarpTable() throws Exception {
@ -471,7 +476,7 @@ public class WarpSignsManagerTest {
// Save // Save
wsm.saveWarpList(); wsm.saveWarpList();
// Default load in constructor check // Default load in constructor check
verify(addon, times(2)).log(eq("Loading warps...")); verify(addon, times(2)).log("Loading warps...");
assertTrue(wsm.getWarpMap(world).isEmpty()); assertTrue(wsm.getWarpMap(world).isEmpty());
} }
} }

View File

@ -4,7 +4,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -53,7 +52,6 @@ public class WarpCommandTest {
private static final String WELCOME_LINE = "[Welcome]"; private static final String WELCOME_LINE = "[Welcome]";
@Mock @Mock
private CompositeCommand ic; private CompositeCommand ic;
private UUID uuid;
@Mock @Mock
private User user; private User user;
@Mock @Mock
@ -78,10 +76,9 @@ public class WarpCommandTest {
private BukkitScheduler sch; private BukkitScheduler sch;
/** /**
* @throws java.lang.Exception
*/ */
@Before @Before
public void setUp() throws Exception { public void setUp() {
// Set up plugin // Set up plugin
BentoBox plugin = mock(BentoBox.class); BentoBox plugin = mock(BentoBox.class);
Whitebox.setInternalState(BentoBox.class, "instance", plugin); Whitebox.setInternalState(BentoBox.class, "instance", plugin);
@ -100,7 +97,7 @@ public class WarpCommandTest {
when(plugin.getIWM()).thenReturn(iwm); when(plugin.getIWM()).thenReturn(iwm);
// Player // Player
uuid = UUID.randomUUID(); UUID uuid = UUID.randomUUID();
when(user.getUniqueId()).thenReturn(uuid); when(user.getUniqueId()).thenReturn(uuid);
when(user.getWorld()).thenReturn(world); when(user.getWorld()).thenReturn(world);
@ -116,7 +113,7 @@ public class WarpCommandTest {
set.add(UUID.randomUUID()); set.add(UUID.randomUUID());
set.add(UUID.randomUUID()); set.add(UUID.randomUUID());
set.add(UUID.randomUUID()); set.add(UUID.randomUUID());
when(wsm.listWarps(eq(world))).thenReturn(set); when(wsm.listWarps(world)).thenReturn(set);
// Players Manager // Players Manager
when(plugin.getPlayers()).thenReturn(pm); when(plugin.getPlayers()).thenReturn(pm);
@ -181,7 +178,7 @@ public class WarpCommandTest {
public void testExecuteUserStringListOfStringNoArgs() { public void testExecuteUserStringListOfStringNoArgs() {
warpCommandWarpCompositeCommand(); warpCommandWarpCompositeCommand();
wc.execute(user, "warp", Collections.emptyList()); wc.execute(user, "warp", Collections.emptyList());
verify(user).sendMessage(eq("commands.help.header"), eq(TextVariables.LABEL), eq("BSkyBlock")); verify(user).sendMessage("commands.help.header", TextVariables.LABEL, "BSkyBlock");
} }
/** /**
@ -191,7 +188,6 @@ public class WarpCommandTest {
public void testExecuteUserStringListOfStringKnownPlayer() { public void testExecuteUserStringListOfStringKnownPlayer() {
warpCommandWarpCompositeCommand(); warpCommandWarpCompositeCommand();
assertTrue(wc.execute(user, "warp", Collections.singletonList("tastybento"))); assertTrue(wc.execute(user, "warp", Collections.singletonList("tastybento")));
//verify(wsm).warpPlayer(eq(world), eq(user), any());
} }
/** /**
@ -201,7 +197,6 @@ public class WarpCommandTest {
public void testExecuteUserStringListOfStringKnownPlayerWarp() { public void testExecuteUserStringListOfStringKnownPlayerWarp() {
warpCommandWarp(); warpCommandWarp();
assertTrue(wc.execute(user, "warp", Collections.singletonList("tastybento"))); assertTrue(wc.execute(user, "warp", Collections.singletonList("tastybento")));
//verify(wsm).warpPlayer(eq(world), eq(user), any());
} }
/** /**
@ -211,7 +206,6 @@ public class WarpCommandTest {
public void testExecuteUserStringListOfStringKnownPlayerMixedCase() { public void testExecuteUserStringListOfStringKnownPlayerMixedCase() {
warpCommandWarpCompositeCommand(); warpCommandWarpCompositeCommand();
assertTrue(wc.execute(user, "warp", Collections.singletonList("tAsTyBEnTo"))); assertTrue(wc.execute(user, "warp", Collections.singletonList("tAsTyBEnTo")));
//verify(wsm).warpPlayer(eq(world), eq(user), any());
} }
/** /**
@ -222,7 +216,6 @@ public class WarpCommandTest {
when(pm.getName(any())).thenReturn("tastybento"); when(pm.getName(any())).thenReturn("tastybento");
warpCommandWarpCompositeCommand(); warpCommandWarpCompositeCommand();
assertTrue(wc.execute(user, "warp", Collections.singletonList("tAsTy"))); assertTrue(wc.execute(user, "warp", Collections.singletonList("tAsTy")));
//verify(wsm).warpPlayer(eq(world), eq(user), any());
} }
@ -233,7 +226,7 @@ public class WarpCommandTest {
public void testExecuteUserStringListOfStringUnknownPlayer() { public void testExecuteUserStringListOfStringUnknownPlayer() {
warpCommandWarpCompositeCommand(); warpCommandWarpCompositeCommand();
assertFalse(wc.execute(user, "warp", Collections.singletonList("LSPVicky"))); assertFalse(wc.execute(user, "warp", Collections.singletonList("LSPVicky")));
verify(user).sendMessage(eq("warps.error.does-not-exist")); verify(user).sendMessage("warps.error.does-not-exist");
} }
/** /**
@ -241,11 +234,11 @@ public class WarpCommandTest {
*/ */
@Test @Test
public void testExecuteUserStringListOfStringNoWarpsYet() { public void testExecuteUserStringListOfStringNoWarpsYet() {
when(wsm.listWarps(eq(world))).thenReturn(Collections.emptySet()); when(wsm.listWarps(world)).thenReturn(Collections.emptySet());
warpCommandWarpCompositeCommand(); warpCommandWarpCompositeCommand();
assertFalse(wc.execute(user, "warp", Collections.singletonList("LSPVicky"))); assertFalse(wc.execute(user, "warp", Collections.singletonList("LSPVicky")));
verify(user).sendMessage(eq("warps.error.no-warps-yet")); verify(user).sendMessage("warps.error.no-warps-yet");
verify(user).sendMessage(eq("warps.warpTip"), eq("[text]"), eq(WELCOME_LINE)); verify(user).sendMessage("warps.warpTip", "[text]", WELCOME_LINE);
} }
/** /**

View File

@ -3,7 +3,6 @@ package world.bentobox.warps.commands;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -66,10 +65,9 @@ public class WarpsCommandTest {
private WarpPanelManager wpm; private WarpPanelManager wpm;
/** /**
* @throws java.lang.Exception
*/ */
@Before @Before
public void setUp() throws Exception { public void setUp() {
// Set up plugin // Set up plugin
BentoBox plugin = mock(BentoBox.class); BentoBox plugin = mock(BentoBox.class);
Whitebox.setInternalState(BentoBox.class, "instance", plugin); Whitebox.setInternalState(BentoBox.class, "instance", plugin);
@ -99,7 +97,7 @@ public class WarpsCommandTest {
set.add(UUID.randomUUID()); set.add(UUID.randomUUID());
set.add(UUID.randomUUID()); set.add(UUID.randomUUID());
set.add(UUID.randomUUID()); set.add(UUID.randomUUID());
when(wsm.listWarps(eq(world))).thenReturn(set); when(wsm.listWarps(world)).thenReturn(set);
// Warp Panel Manager // Warp Panel Manager
when(addon.getWarpPanelManager()).thenReturn(wpm); when(addon.getWarpPanelManager()).thenReturn(wpm);
@ -144,11 +142,11 @@ public class WarpsCommandTest {
*/ */
@Test @Test
public void testExecuteUserStringListOfStringNoWarpsYet() { public void testExecuteUserStringListOfStringNoWarpsYet() {
when(wsm.listWarps(eq(world))).thenReturn(Collections.emptySet()); when(wsm.listWarps(world)).thenReturn(Collections.emptySet());
warpCommandWarpsCompositeCommand(); warpCommandWarpsCompositeCommand();
assertFalse(wc.execute(user, "warps", Collections.emptyList())); assertFalse(wc.execute(user, "warps", Collections.emptyList()));
verify(user).sendMessage(eq("warps.error.no-warps-yet")); verify(user).sendMessage("warps.error.no-warps-yet");
verify(user).sendMessage(eq("warps.warpTip"), eq("[text]"), eq(WELCOME_LINE)); verify(user).sendMessage("warps.warpTip", "[text]", WELCOME_LINE);
} }
/** /**
@ -156,11 +154,11 @@ public class WarpsCommandTest {
*/ */
@Test @Test
public void testExecuteUserStringListOfStringNoWarpsYetNoAddon() { public void testExecuteUserStringListOfStringNoWarpsYetNoAddon() {
when(wsm.listWarps(eq(world))).thenReturn(Collections.emptySet()); when(wsm.listWarps(world)).thenReturn(Collections.emptySet());
warpCommandWarps(); warpCommandWarps();
assertFalse(wc.execute(user, "warps", Collections.emptyList())); assertFalse(wc.execute(user, "warps", Collections.emptyList()));
verify(user).sendMessage(eq("warps.error.no-warps-yet")); verify(user).sendMessage("warps.error.no-warps-yet");
verify(user).sendMessage(eq("warps.warpTip"), eq("[text]"), eq(WELCOME_LINE)); verify(user).sendMessage("warps.warpTip", "[text]", WELCOME_LINE);
} }
/** /**

View File

@ -6,6 +6,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
@ -73,7 +74,6 @@ public class WarpSignsListenerTest {
@Mock @Mock
private WarpSignsManager wsm; private WarpSignsManager wsm;
private PluginManager pm; private PluginManager pm;
private UUID uuid;
private String[] lines; private String[] lines;
@Mock @Mock
private FileConfiguration config; private FileConfiguration config;
@ -85,7 +85,7 @@ public class WarpSignsListenerTest {
private IslandWorldManager iwm; private IslandWorldManager iwm;
@Before @Before
public void setUp() throws Exception { public void setUp() {
// Bukkit // Bukkit
PowerMockito.mockStatic(Bukkit.class); PowerMockito.mockStatic(Bukkit.class);
pm = mock(PluginManager.class); pm = mock(PluginManager.class);
@ -114,10 +114,10 @@ public class WarpSignsListenerTest {
when(block.getWorld()).thenReturn(world); when(block.getWorld()).thenReturn(world);
// Player // Player
when(player.hasPermission(anyString())).thenReturn(false); when(player.hasPermission(anyString())).thenReturn(false);
uuid = UUID.randomUUID(); UUID uuid = UUID.randomUUID();
when(player.getUniqueId()).thenReturn(uuid); when(player.getUniqueId()).thenReturn(uuid);
s = mock(Sign.class); s = mock(Sign.class);
when(s.getLine(Mockito.anyInt())).thenReturn(ChatColor.GREEN + "[WELCOME]"); when(s.getLine(anyInt())).thenReturn(ChatColor.GREEN + "[WELCOME]");
when(block.getState()).thenReturn(s); when(block.getState()).thenReturn(s);
// warp signs manager // warp signs manager
when(addon.getWarpSignsManager()).thenReturn(wsm); when(addon.getWarpSignsManager()).thenReturn(wsm);
@ -128,7 +128,7 @@ public class WarpSignsListenerTest {
when(block.getLocation()).thenReturn(location); when(block.getLocation()).thenReturn(location);
list.put(uuid, location); list.put(uuid, location);
// Player is in world // Player is in world
when(wsm.getWarpMap(Mockito.eq(world))).thenReturn(list); when(wsm.getWarpMap(world)).thenReturn(list);
//Player has a warp sign already here //Player has a warp sign already here
when(wsm.getWarp(any(), any())).thenReturn(location); when(wsm.getWarp(any(), any())).thenReturn(location);
// Unique spot // Unique spot
@ -199,7 +199,7 @@ public class WarpSignsListenerTest {
when(addon.inRegisteredWorld(any())).thenReturn(false); when(addon.inRegisteredWorld(any())).thenReturn(false);
wsl.onSignBreak(e); wsl.onSignBreak(e);
assertFalse(e.isCancelled()); assertFalse(e.isCancelled());
verify(addon).inRegisteredWorld(Mockito.eq(world)); verify(addon).inRegisteredWorld(world);
} }
@Test @Test
@ -209,7 +209,7 @@ public class WarpSignsListenerTest {
when(s.getLine(Mockito.anyInt())).thenReturn(ChatColor.RED + "[WELCOME]"); when(s.getLine(Mockito.anyInt())).thenReturn(ChatColor.RED + "[WELCOME]");
wsl.onSignBreak(e); wsl.onSignBreak(e);
assertFalse(e.isCancelled()); assertFalse(e.isCancelled());
verify(s).getLine(Mockito.eq(0)); verify(s).getLine(0);
verify(settings).getWelcomeLine(); verify(settings).getWelcomeLine();
} }
@ -222,7 +222,7 @@ public class WarpSignsListenerTest {
when(s.getLocation()).thenReturn(mock(Location.class)); when(s.getLocation()).thenReturn(mock(Location.class));
wsl.onSignBreak(e); wsl.onSignBreak(e);
assertFalse(e.isCancelled()); assertFalse(e.isCancelled());
verify(wsm).getWarpMap(Mockito.eq(world)); verify(wsm).getWarpMap(world);
verify(s).getLocation(); verify(s).getLocation();
} }
@ -282,7 +282,7 @@ public class WarpSignsListenerTest {
SignChangeEvent e = new SignChangeEvent(block, player, lines); SignChangeEvent e = new SignChangeEvent(block, player, lines);
when(addon.inRegisteredWorld(any())).thenReturn(false); when(addon.inRegisteredWorld(any())).thenReturn(false);
wsl.onSignWarpCreate(e); wsl.onSignWarpCreate(e);
verify(addon).inRegisteredWorld(Mockito.eq(world)); verify(addon).inRegisteredWorld(world);
} }
@Test @Test