1
0
mirror of https://github.com/BentoBoxWorld/Warps.git synced 2024-06-26 06:34:57 +02:00

Compare commits

..

83 Commits

Author SHA1 Message Date
tastybento
18b63f4e79
Merge pull request #135 from TreemanKing/toggle-warp
feat: toggle warp command
2024-06-21 20:18:57 -07:00
TreemanK
4bacbd7c5a feat: suggestions
- getToggleCommand is linked to toggleWarpCommand instead of hardcoded
- warpSigns is now null and not empty
2024-06-22 13:16:47 +10:00
tastybento
7f9f35253d
Merge pull request #136 from TreemanKing/fix-other-worlds
fix (partial): other worlds can be used
2024-06-21 08:16:47 -07:00
TreemanK
599a6e1d08 style: added TODO
Currently, `noLevelOrIsland and hasCorrectIslandRank` require the sign to be on an island. Currently this means the flag/level requirement are non-existent in the case of a sign being placed on a non-BSB island. This gives a possible solution if new API comes to light.
2024-06-22 00:06:21 +10:00
TreemanK
1054518831 fix: fix create warp/sign in non-island world
Currently, you can't create a warp in another world (even with permissions) as it goes into hasCorrectIslandRank. In this case, it is always false as there is no island at the block location meaning it will always go into this whilst creating a warp in other worlds.
2024-06-21 23:06:02 +10:00
TreemanK
abd526b06d feat: add toggle event 2024-06-21 20:42:31 +10:00
TreemanK
eeead7fb49 feat: toggle warp command 2024-06-21 20:19:24 +10:00
TreemanK
ef81a1c2f0 style: change method name to getWarpLocation
note `line 294` of `warp.java`, I am unsure what this does and whether it should be `getWarpLocation` or not. I will leave it for the time being.
2024-06-21 02:23:38 +10:00
TreemanK
64f8a4899a feat: make sure old data is not lost!
Now, I was thinking if there is a way to directly convert it but there isn't because of the way it was structured. This *ISN'T* the best way around things but if someone can find a better way around it, be my guest.
2024-06-21 01:49:30 +10:00
TreemanK
0a343219bc feat: changed location to playerwarp in preparation of toggle state 2024-06-20 21:57:50 +10:00
tastybento
0a12a26b06
Merge pull request #134 from BentoBoxWorld/gitlocalize-29839
French translation
2024-06-08 10:12:36 -07:00
ISOURA
b860a4dac5 Translate fr.yml via GitLocalize 2024-06-08 17:08:20 +00:00
tastybento
2da0e5e82b
Merge pull request #133 from RUYSUE/develop
updated zh-CN locale
2024-06-08 08:52:53 -07:00
RUYSUE
a39b6a3f4a
Update zh-CN.yml 2024-06-08 17:20:14 +08:00
tastybento
d70ee5d755
Merge pull request #132 from BentoBoxWorld/131_WarpCreateEvent_doesn't_fire
Call events correctly. #131
2024-06-05 14:12:29 -07:00
tastybento
efc6b795d1 Call events correctly. #131 2024-06-05 14:09:02 -07:00
tastybento
519a2d05fc Version 1.15.0 2024-02-03 08:30:12 -08:00
tastybento
86c089b694 Update tipped arrows in GUI Panel 2024-01-21 09:09:17 -08:00
tastybento
3417633c4d Version 1.14.1 2024-01-21 09:09:12 -08:00
tastybento
b16d5102b1
Merge pull request #129 from BentoBoxWorld/tastybento-patch-1
Update addon.yml
2024-01-12 14:37:29 -08:00
tastybento
4375eba030
Update addon.yml
Fix because the warps command got its own perm from a1e03af
2024-01-12 14:36:38 -08:00
tastybento
bc1e92ee8d Add support for hanging signs.
Warps to below the sign.
2024-01-06 22:00:24 +09:00
tastybento
b88497397f
Merge pull request #126 from BentoBoxWorld/gitlocalize-27267
Add Ukrainian locale
2023-11-26 10:00:25 -08:00
GIGABAIT
b45c88025f Translate uk.yml via GitLocalize 2023-11-26 11:18:41 +00:00
tastybento
3c9515295d Merge branch 'develop' of https://github.com/BentoBoxWorld/Warps.git into develop 2023-11-12 13:25:11 -08:00
tastybento
82a0630ca3 BentoBox API 2.0.0 2023-11-12 13:25:03 -08:00
BONNe
6dbdb0f8aa
Update WarpsCommandTest.java 2023-11-05 22:00:28 +02:00
BONNe
a1e03af13a
Update WarpsCommand.java 2023-11-05 21:35:59 +02:00
tastybento
2558d9d1ab
Merge pull request #124 from rchomczyk/fix-pl-translation
Improve polish translation
2023-09-04 07:46:24 -07:00
Rafał Chomczyk
d346b7864e
Fix invalid placeholder name for warp's description; improve translations by a little, fix typo 2023-09-03 17:50:30 +02:00
BONNe
0e1cd1353c
Version Up 2023-07-26 15:37:35 +03:00
tastybento
9657d11af7
Update pom.xml 2023-07-10 21:39:57 -07:00
tastybento
ab1a1e203c Update Jacoco 2023-07-10 21:24:40 -07:00
tastybento
1a90acb65f Update GitHub Action versions 2023-06-24 13:49:47 -07:00
tastybento
ae172b9fdf Minor variable rename 2023-06-24 13:49:33 -07:00
tastybento
ecebbcd039
Merge pull request #122 from BentoBoxWorld/gitlocalize-24193
Spanish
2023-05-29 09:40:06 -07:00
tastybento
3faed651aa
Merge pull request #123 from BentoBoxWorld/gitlocalize-24194
Indonesian
2023-05-29 09:39:49 -07:00
Dusty
0585fd7f3a Translate id.yml via GitLocalize 2023-05-29 16:35:40 +00:00
Espan
2f59225718 Translate es.yml via GitLocalize 2023-05-29 16:35:13 +00:00
tastybento
9e57851c62 Update GitHub build script to Java 17 2023-04-16 11:02:01 -07:00
tastybento
b998b46fd5 User BentoBox release build 2023-04-16 11:00:06 -07:00
tastybento
cb165e52b0 Updated POM; fixed tests. 2023-04-15 13:08:55 -07:00
BONNe
ebb3f05d78
Merge pull request #119 from BentoBoxWorld/return-to-plugin
Return to plugin.yml
2023-04-08 19:10:40 +03:00
BONNe
fe6b020ac8
Update WarpsPladdon.java 2023-04-08 19:10:32 +03:00
BONNe
d2dde61d8b
Update pom.xml 2023-04-08 19:10:15 +03:00
BONNe
e58010547b
Create plugin.yml 2023-04-08 19:09:38 +03:00
tastybento
5a9f6495ad Updated pladdon dependencies. Removed unused imports. 2023-03-25 10:12:07 -07:00
tastybento
ff4850d32a Use addon name in annotation 2023-03-25 09:59:53 -07:00
DevSolaris
7a26acefd9
Flip bool expression (#114) 2023-02-12 10:44:49 -08:00
tastybento
2be57a66d2 Fix SonarCloud bugs and smells. 2023-02-09 17:44:25 -08:00
tastybento
67c5c9f8c3 Updated Jacoco POM 2023-02-09 17:38:25 -08:00
tastybento
62f1f2e966
Add ${argLine} to get jacoco coverage 2023-02-09 15:13:34 -08:00
BONNe
5a37c3da75
Merge pull request #118 from BentoBoxWorld/gitlocalize-22781
Update NL
2023-01-24 15:18:17 +02:00
DevSolaris
94e9208941 Translate nl.yml via GitLocalize 2023-01-24 13:18:06 +00:00
BONNe
225b4d66f8
Update Warp.java 2023-01-19 23:15:38 +02:00
BONNe
d3b45396fd
Add missing import 2023-01-19 23:10:00 +02:00
BONNe
d2b9540650
Update locale 2023-01-19 23:06:57 +02:00
BONNe
363a628244
Improve create warps flag.
Rename the flag to PLACE_WARP as it is a more proper name.
Also, add a click handler that limits setting value from member to owner, as visitors should not be allowed.

Also, set default value outside island range as false.
2023-01-19 23:06:45 +02:00
DevSolaris
8be844b59f
Closes #69 - Fix message from being sent when the user is banned. (#116) 2023-01-19 21:59:39 +01:00
DevSolaris
b3a36c75bb
Create set warp flag (#117) 2023-01-19 21:56:31 +01:00
DevSolaris
7dbb5d39ad
Add gamemode placeholder to message (#115) 2023-01-18 22:14:50 +01:00
BONNe
fb1090717b
Merge pull request #113 from BentoBoxWorld/gitlocalize-20471
Update Polish translation
2022-08-23 10:54:09 +03:00
mt-gitlocalize
39b94e09d8 Translate pl.yml via GitLocalize 2022-08-23 07:53:37 +00:00
wiktorm12
5716214527 Translate pl.yml via GitLocalize 2022-08-23 07:53:37 +00:00
BONNe
153e8be6a0
Init next version 2022-05-17 12:32:25 +03:00
BONNe
0dea651274
Fix build number for warps
1.11.2 was already released.
2022-05-17 12:20:13 +03:00
BONNe
63b51fb26e
Merge pull request #109 from BentoBoxWorld/gitlocalize-18727
Update German translation
2022-04-09 12:32:55 +03:00
Patrick
15a699037a Translate de.yml via GitLocalize 2022-04-09 09:30:14 +00:00
BONNe
cbaf6ce16c Implement customizable Warps Panel.
Relates to #BentoBox/issues/1931
These changes includes to removing some obsolete config settings and locales string.
Also, moved some classes around to clean up directory.
2022-03-11 12:34:16 +02:00
Huynh Tien
b12a6dcff9
Update id.yml (#108) 2022-01-28 07:13:25 -08:00
gitlocalize-app[bot]
89bcc54e23
Translate it.yml via GitLocalize (#107)
Co-authored-by: Pirlas <alexpirlas@outlook.it>
2022-01-01 16:47:50 -08:00
gitlocalize-app[bot]
6db80f73f8
Taiwan translation (#106)
* Translate zh-TW.yml via GitLocalize

* Translate zh-TW.yml via GitLocalize

Co-authored-by: Shaowing <lien78520@gmail.com>
Co-authored-by: mt-gitlocalize <mt@gitlocalize.com>
2022-01-01 16:47:40 -08:00
gitlocalize-app[bot]
87d04302d2
Indonesian Translation (#105)
* Translate id.yml via GitLocalize

* Translate id.yml via GitLocalize

* Translate id.yml via GitLocalize

Co-authored-by: Alunite? <xcionsspro30@gmail.com>
Co-authored-by: mt-gitlocalize <mt@gitlocalize.com>
Co-authored-by: gitlocalize-app[bot] <55277160+gitlocalize-app[bot]@users.noreply.github.com>
2022-01-01 16:47:29 -08:00
gitlocalize-app[bot]
9b0f00f2a0
Translate hu.yml via GitLocalize (#104)
Co-authored-by: driverdakid <tamascsiszar99@icloud.com>
2022-01-01 16:47:18 -08:00
gitlocalize-app[bot]
048f7237da
French translation (#103)
* Translate fr.yml via GitLocalize

* Translate fr.yml via GitLocalize

Co-authored-by: Aksel <afgameytb@gmail.com>
Co-authored-by: HipppB <hippolyte.bach@eleve.isep.fr>
2022-01-01 16:47:08 -08:00
gitlocalize-app[bot]
49d461d224
Translate tr.yml via GitLocalize (#102)
Co-authored-by: Over_Brave <soncesurlar@gmail.com>
2022-01-01 16:46:54 -08:00
Huynh Tien
6cfaa0e9c0
Fix null player on removeWarp (#100) 2021-12-31 08:25:05 -08:00
tastybento
9290503be3 Fix plugin.yml 2021-12-21 14:13:48 -08:00
tastybento
079dba0f41 Merge branch 'develop' of https://github.com/BentoBoxWorld/Warps.git into develop 2021-10-01 19:04:19 -07:00
tastybento
60c427c2a9 Build to BentoBox 1.18 API 2021-10-01 19:04:09 -07:00
KrazyxWolf
6caa652162
Update es.yml (#98) 2021-08-26 18:02:37 -07:00
tastybento
4ebaa22f37 Renamed plugin Pladdon 2021-08-12 18:48:39 -07:00
tastybento
f0780d91ba Version 1.11.2 2021-08-12 18:48:29 -07:00
42 changed files with 1934 additions and 988 deletions

View File

@ -11,22 +11,22 @@ jobs:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
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
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'adopt'
java-version: '16'
java-version: '17'
- name: Cache SonarCloud packages
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache Maven packages
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}

20
pom.xml
View File

@ -54,19 +54,19 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>16</java.version>
<java.version>17</java.version>
<!-- Non-minecraft related dependencies -->
<powermock.version>2.0.9</powermock.version>
<!-- More visible way how to change dependency versions -->
<spigot.version>1.17-R0.1-SNAPSHOT</spigot.version>
<bentobox.version>1.18.0-SNAPSHOT</bentobox.version>
<spigot.version>1.19.4-R0.1-SNAPSHOT</spigot.version>
<bentobox.version>2.0.0-SNAPSHOT</bentobox.version>
<level.version>2.7.0-SNAPSHOT</level.version>
<!-- Revision variable removes warning about dynamic version -->
<revision>${build.version}-SNAPSHOT</revision>
<!-- Do not change unless you want different name for local builds. -->
<build.number>-LOCAL</build.number>
<!-- This allows to change between versions. -->
<build.version>1.11.2</build.version>
<build.version>1.15.0</build.version>
<!-- Sonar Cloud -->
<sonar.projectKey>BentoBoxWorld_Warps</sonar.projectKey>
<sonar.organization>bentobox-world</sonar.organization>
@ -229,6 +229,7 @@
<version>3.0.0-M5</version>
<configuration>
<argLine>
${argLine}
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/java.math=ALL-UNNAMED
--add-opens java.base/java.io=ALL-UNNAMED
@ -311,7 +312,7 @@
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.3</version>
<version>0.8.10</version>
<configuration>
<append>true</append>
<excludes>
@ -322,16 +323,21 @@
</configuration>
<executions>
<execution>
<id>pre-unit-test</id>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>post-unit-test</id>
<id>report</id>
<goals>
<goal>report</goal>
</goals>
<configuration>
<formats>
<format>XML</format>
</formats>
</configuration>
</execution>
</executions>
</plugin>

View File

@ -7,16 +7,24 @@ import java.util.Set;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.configuration.Config;
import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.api.flags.clicklisteners.CycleClick;
import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.bentobox.util.Util;
import world.bentobox.level.Level;
import world.bentobox.warps.commands.ToggleWarpCommand;
import world.bentobox.warps.commands.WarpCommand;
import world.bentobox.warps.commands.WarpsCommand;
import world.bentobox.warps.config.Settings;
import world.bentobox.warps.listeners.WarpSignsListener;
import world.bentobox.warps.managers.SignCacheManager;
import world.bentobox.warps.managers.WarpSignsManager;
/**
* Addin to BentoBox that enables welcome warp signs
@ -38,16 +46,16 @@ public class Warp extends Addon {
*/
public static final String WELCOME_WARP_SIGNS = "welcomewarpsigns";
/**
* Warp panel Manager
*/
private WarpPanelManager warpPanelManager;
/**
* Worlds Sign manager.
*/
private WarpSignsManager warpSignsManager;
/**
* Sign Cache Manager
*/
private SignCacheManager signCacheManager;
/**
* This variable stores in which worlds this addon is working.
*/
@ -68,6 +76,11 @@ public class Warp extends Addon {
*/
private Config<Settings> settingsConfig;
/**
* Create Warp Flag
*/
private Flag createWarpFlag;
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
@ -88,6 +101,7 @@ public class Warp extends Addon {
// Load the master warp and warps command
new WarpCommand(this);
new WarpsCommand(this);
new ToggleWarpCommand(this);
}
}
@ -128,6 +142,7 @@ public class Warp extends Addon {
new WarpCommand(this, gameModeAddon.getPlayerCommand().get());
new WarpsCommand(this, gameModeAddon.getPlayerCommand().get());
new ToggleWarpCommand(this, gameModeAddon.getPlayerCommand().get());
this.hooked = true;
}
});
@ -136,13 +151,25 @@ public class Warp extends Addon {
{
// Start warp signs
warpSignsManager = new WarpSignsManager(this, this.getPlugin());
warpPanelManager = new WarpPanelManager(this);
signCacheManager = new SignCacheManager(this);
// Load the listener
this.registerListener(new WarpSignsListener(this));
} else {
logWarning("Addon did not hook into anything and is not running stand-alone");
this.setState(State.DISABLED);
}
this.createWarpFlag = new Flag.Builder("PLACE_WARP", Material.OAK_SIGN)
.addon(this)
.defaultRank(RanksManager.MEMBER_RANK)
.clickHandler(new CycleClick("PLACE_WARP",
RanksManager.MEMBER_RANK,
RanksManager.OWNER_RANK))
.defaultSetting(false)
.mode(Flag.Mode.EXPERT)
.build();
getPlugin().getFlagsManager().registerFlag(this, this.createWarpFlag);
}
@ -169,17 +196,21 @@ public class Warp extends Addon {
this.setState(State.DISABLED);
return false;
}
// Save existing panels.
this.saveResource("panels/warps_panel.yml", false);
settingsConfig.saveConfigObject(settings);
return true;
}
/**
* Get warp panel manager
* @return Warp Panel Manager
* Get sign cache manager
* @return Sign Cache Manager
*/
public WarpPanelManager getWarpPanelManager() {
return warpPanelManager;
public SignCacheManager getSignCacheManager() {
return signCacheManager;
}
public WarpSignsManager getWarpSignsManager() {
@ -206,6 +237,13 @@ public class Warp extends Addon {
return settings;
}
/**
* @return the createWarpFlag
*/
public Flag getCreateWarpFlag() {
return createWarpFlag;
}
/**
* Get the island level
* @param world - world
@ -217,8 +255,11 @@ public class Warp extends Addon {
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);
final Level addon = (Level) l;
//getGameModes is a list of gamemodes that Level is DISABLED in,
//so we need the opposite of the contains.
if (!name.isEmpty() && !addon.getSettings().getGameModes().contains(name)) {
return addon.getIslandLevel(world, uniqueId);
}
return null;
}).orElse(null);
@ -250,7 +291,7 @@ public class Warp extends Addon {
}
return switch (requestLabel) {
case "getSortedWarps" -> getWarpSignsManager().getSortedWarps(world);
case "getWarp" -> uuid == null ? null : getWarpSignsManager().getWarp(world, uuid);
case "getWarp" -> uuid == null ? null : getWarpSignsManager().getWarpLocation(world, uuid);
case "getWarpMap" -> getWarpSignsManager().getWarpMap(world);
case "hasWarp" -> uuid == null ? null : getWarpSignsManager().hasWarp(world, uuid);
case "listWarps" -> getWarpSignsManager().listWarps(world);

View File

@ -1,187 +0,0 @@
package world.bentobox.warps;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.inventory.ItemStack;
import org.eclipse.jdt.annotation.NonNull;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
import world.bentobox.bentobox.api.user.User;
public class WarpPanelManager {
private static final int PANEL_MAX_SIZE = 52;
private final Warp addon;
// This is a cache of signs
private final SignCacheManager signCacheManager;
public WarpPanelManager(Warp addon) {
this.addon = addon;
signCacheManager = new SignCacheManager(addon);
}
private PanelItem getPanelItem(World world, UUID warpOwner, SignCacheItem sign) {
PanelItemBuilder pib = new PanelItemBuilder()
.name(addon.getSettings().getNameFormat() + addon.getPlugin().getPlayers().getName(warpOwner))
.description(sign.getSignText())
.clickHandler((panel, clicker, click, slot) -> hander(world, clicker, warpOwner));
Material icon = sign.getType();
if (icon.equals(Material.PLAYER_HEAD)) {
return pib.icon(addon.getPlayers().getName(warpOwner)).build();
} else {
return pib.icon(icon).build();
}
}
private boolean hander(World world, User clicker, UUID warpOwner) {
clicker.closeInventory();
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);
clicker.getPlayer().performCommand((playerCommand.isEmpty() ? "" : playerCommand + " ") + command);
return true;
}
private PanelItem getRandomButton(World world, User user, UUID warpOwner) {
return new PanelItemBuilder()
.name(addon.getSettings().getNameFormat() + user.getTranslation("warps.random"))
.clickHandler((panel, clicker, click, slot) -> hander(world, clicker, warpOwner))
.icon(Material.END_CRYSTAL).build();
}
/**
* Show the warp panel for the user
* @param world - world
* @param user - user
* @param index - page to show - 0 is first
*/
public void showWarpPanel(World world, User user, int index) {
PanelBuilder panelBuilder = new PanelBuilder()
.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()) {
warps.add(0, warps.get(new Random().nextInt(warps.size())));
}
}
int buildMainBody(PanelBuilder panelBuilder, User user, int index, World world, List<UUID> warps) {
if (index < 0) {
index = 0;
} else if (index > (warps.size() / PANEL_MAX_SIZE)) {
index = warps.size() / PANEL_MAX_SIZE;
}
int i = index * PANEL_MAX_SIZE;
for (; panelBuilder.getItems().size() < PANEL_MAX_SIZE && i < warps.size(); i++) {
UUID warpOwner = warps.get(i);
if (addon.getSettings().isRandomAllowed() && i == 0) {
panelBuilder.item(getRandomButton(world, user, warpOwner));
} else {
@NonNull
SignCacheItem sign = signCacheManager.getSignItem(world, warpOwner);
if (sign.isReal()) {
panelBuilder.item(getPanelItem(world, warpOwner, sign));
} else {
addon.getWarpSignsManager().removeWarpFromMap(world, warpOwner);
}
}
}
return i;
}
/**
* Add Next and Previous icons to navigate
* @param panelBuilder - the panel builder
* @param user - user
* @param world - world
* @param numOfItems - number of items shown so far including in previous panels
* @param panelNum - panel number (page)
* @param totalNum - total number of items in the list
*/
void addNavigation(PanelBuilder panelBuilder, User user, World world, int numOfItems, int panelNum, int totalNum) {
// Previous
if (panelNum > 0 && numOfItems > PANEL_MAX_SIZE) {
// Previous
panelBuilder.item(new PanelItemBuilder()
.name(user.getTranslation("warps.previous"))
.icon(new ItemStack(Material.COBBLESTONE))
.clickHandler((panel, clicker, click, slot) -> {
user.closeInventory();
showWarpPanel(world, user, panelNum-1);
return true;
}).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
* @param world - world
* @param key - uuid of owner
* @return true if the item was removed from the cache
*/
public boolean removeWarp(World world, UUID key) {
return signCacheManager.removeWarp(world, key);
}
public void saveCache() {
signCacheManager.saveCache();
}
}

View File

@ -1,8 +1,10 @@
package world.bentobox.warps;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.addons.Pladdon;
public class WarpsPladdon extends Pladdon {
@Override

View File

@ -0,0 +1,61 @@
package world.bentobox.warps.commands;
import org.bukkit.Bukkit;
import org.bukkit.World;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.warps.Warp;
import world.bentobox.warps.event.WarpToggleEvent;
import world.bentobox.warps.objects.PlayerWarp;
import java.util.List;
import java.util.UUID;
public class ToggleWarpCommand extends CompositeCommand {
private final Warp addon;
public ToggleWarpCommand(Warp addon, CompositeCommand bsbIslandCmd) {
super(bsbIslandCmd, addon.getSettings().getToggleWarpCommand());
this.addon = addon;
}
public ToggleWarpCommand(Warp addon) {
super(addon.getSettings().getToggleWarpCommand());
this.addon = addon;
}
@Override
public void setup() {
this.setPermission(this.getParent() == null ? Warp.WELCOME_WARP_SIGNS + ".togglewarp" : "island.warp.toggle");
this.setOnlyPlayer(true);
this.setDescription("togglewarp.help.description");
}
@Override
public boolean execute(User user, String s, List<String> list) {
UUID userUUID = user.getUniqueId();
World userWorld = user.getWorld();
// Check if the user has a warp
boolean hasWarp = addon.getWarpSignsManager().hasWarp(userWorld, userUUID);
if (hasWarp) {
// If the user has a warp, toggle its visibility
PlayerWarp warp = addon.getWarpSignsManager().getPlayerWarp(userWorld, userUUID);
// Check extreme case if PlayerWarp is null
if (warp == null) {
user.sendMessage("togglewarp.error.generic");
return false;
}
warp.toggle();
Bukkit.getPluginManager().callEvent(new WarpToggleEvent(userUUID, warp));
String message = warp.isEnabled() ? "togglewarp.enabled" : "togglewarp.disabled";
user.sendMessage(message);
} else {
user.sendMessage("togglewarp.error.no-warp");
}
return false;
}
}

View File

@ -50,12 +50,12 @@ public class WarpCommand extends DelayedTeleportCommand {
user.sendMessage("warps.warpTip", "[text]", addon.getSettings().getWelcomeLine());
return false;
} else {
// Attemp to find warp with exact player's name
// Attempt to find warp with exact player's name
UUID foundWarp = warpList.stream().filter(u -> getPlayers().getName(u).equalsIgnoreCase(args.get(0))).findFirst().orElse(null);
if (foundWarp == null) {
// Atempt to find warp which starts with the given name
// Attempt to find warp which starts with the given name
UUID foundAlernativeWarp = warpList.stream().filter(u -> getPlayers().getName(u).toLowerCase().startsWith(args.get(0).toLowerCase())).findFirst().orElse(null);
if (foundAlernativeWarp == null) {

View File

@ -7,6 +7,8 @@ import org.bukkit.World;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.warps.Warp;
import world.bentobox.warps.panels.WarpsPanel;
/**
* Handles the warps command
@ -32,7 +34,7 @@ public class WarpsCommand extends CompositeCommand {
*/
@Override
public void setup() {
this.setPermission(this.getParent() == null ? Warp.WELCOME_WARP_SIGNS + ".warp" : "island.warp");
this.setPermission(this.getParent() == null ? Warp.WELCOME_WARP_SIGNS + ".warps" : "island.warps");
this.setOnlyPlayer(true);
this.setDescription("warps.help.description");
}
@ -51,7 +53,9 @@ public class WarpsCommand extends CompositeCommand {
user.sendMessage("warps.warpTip", "[text]", addon.getSettings().getWelcomeLine());
return false;
}
addon.getWarpPanelManager().showWarpPanel(world, user, 0);
WarpsPanel.openPanel(this.addon, world, user);
return true;
}

View File

@ -23,20 +23,19 @@ public class Settings implements ConfigObject
@ConfigEntry(path = "warplevelrestriction")
private int warpLevelRestriction = 10;
@ConfigComment("")
@ConfigComment("Should warps be removed when the island protection settings")
@ConfigComment("change, and the owner of the warp does no longer have")
@ConfigComment("the correct rank")
@ConfigEntry(path = "removeExistingWarpsWhenFlagChanges")
private boolean removeExistingWarpsWhenFlagChanges = false;
@ConfigComment("")
@ConfigComment("Text that player must put on sign to make it a warp sign")
@ConfigComment("Not case sensitive!")
@ConfigEntry(path = "welcomeLine")
private String welcomeLine = "[Welcome]";
@ConfigComment("")
@ConfigComment("Icon that will be displayed in Warps list. SIGN counts for any kind of sign and the type of")
@ConfigComment("wood used will be reflected in the panel if the server supports it.")
@ConfigComment("It uses native Minecraft material strings, but using string 'PLAYER_HEAD', it is possible to")
@ConfigComment("use player heads instead. Beware that Mojang API rate limiting may prevent heads from loading.")
@ConfigEntry(path = "icon")
private String icon = "SIGN";
@ConfigComment("")
@ConfigComment("This list stores GameModes in which Level addon should not work.")
@ConfigComment("To disable addon it is necessary to write its name in new line that starts with -. Example:")
@ -45,23 +44,12 @@ public class Settings implements ConfigObject
@ConfigEntry(path = "disabled-gamemodes")
private Set<String> disabledGameModes = new HashSet<>();
@ConfigComment("")
@ConfigComment("Warp panel name formatting.")
@ConfigComment("Example: &c will make names red. &f is white")
@ConfigEntry(path = "name-format")
private String nameFormat = "&f";
@ConfigComment("")
@ConfigComment("Warp panel default lore formatting.")
@ConfigComment("Example: &c will make lore red. &f is white")
@ConfigEntry(path = "lore-format")
private String loreFormat = "&f";
@ConfigComment("")
@ConfigComment("Allow random teleport - adds a button to the warp panel that goes to a random warp sign")
@ConfigEntry(path = "random-allowed")
private boolean randomAllowed = true;
@ConfigComment("")
@ConfigComment("Allow use in other worlds. Players must have the welcomewarpsigns.warp permission.")
@ConfigEntry(path = "allow-in-other-worlds")
@ -73,7 +61,8 @@ public class Settings implements ConfigObject
String warpCommand = "warp";
@ConfigEntry(path = "warps-command")
String warpsCommand = "warps";
@ConfigEntry(path = "togglewarp-command")
String toggleWarpCommand = "togglewarp";
// ---------------------------------------------------------------------
// Section: Constructor
@ -155,42 +144,6 @@ public class Settings implements ConfigObject
}
/**
* This method returns the icon object.
* @return the icon object.
*/
public String getIcon()
{
return icon;
}
/**
* This method sets the icon object value.
* @param icon the icon object new value.
*/
public void setIcon(String icon)
{
this.icon = icon;
}
/**
* @return the nameFormat
*/
public String getNameFormat() {
return nameFormat;
}
/**
* @param nameFormat the nameFormat to set
*/
public void setNameFormat(String nameFormat) {
this.nameFormat = nameFormat;
}
/**
* @return the loreFormat
*/
@ -207,22 +160,6 @@ public class Settings implements ConfigObject
}
/**
* @return the randomAllowed
*/
public boolean isRandomAllowed() {
return randomAllowed;
}
/**
* @param randomAllowed the randomAllowed to set
*/
public void setRandomAllowed(boolean randomAllowed) {
this.randomAllowed = randomAllowed;
}
/**
* @return the allowInOtherWorlds
*/
@ -271,4 +208,31 @@ public class Settings implements ConfigObject
}
/**
* @return the toggleWarpCommand
*/
public String getToggleWarpCommand() {
return toggleWarpCommand;
}
/**
* @param toggleWarpCommand the toggleWarpCommand to set
*/
public void setToggleWarpCommand(String toggleWarpCommand) {
this.toggleWarpCommand = toggleWarpCommand;
}
/**
* @return the removeExistingWarpsWhenFlagChanges
*/
public boolean getRemoveExistingWarpsWhenFlagChanges() {
return removeExistingWarpsWhenFlagChanges;
}
/**
* @param removeExistingWarpsWhenFlagChanges the removeExistingWarpsWhenFlagChanges to set
*/
public void setRemoveExistingWarpsWhenFlagChanges(boolean removeExistingWarpsWhenFlagChanges) {
this.removeExistingWarpsWhenFlagChanges = removeExistingWarpsWhenFlagChanges;
}
}

View File

@ -0,0 +1,72 @@
package world.bentobox.warps.event;
import org.bukkit.Location;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import world.bentobox.warps.objects.PlayerWarp;
import java.util.UUID;
/**
* This event is fired when a warp is toggled
* A Listener to this event can use it only to get information. e.g: broadcast something
*
* @since 1.16.0
* @author TreemanKing
*/
public class WarpToggleEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private final UUID user;
private final PlayerWarp playerWarp;
public WarpToggleEvent(UUID user, PlayerWarp playerWarp) {
this.playerWarp = playerWarp;
this.user = user;
}
/**
* Gets the user who has toggled the warp
*
* @return the UUID of the player who toggled the warp
*/
public UUID getUser() {
return user;
}
/**
* Gets the state of the warp
*
* @return true if the warp is enabled, false otherwise
*/
public boolean isEnabled() {
return playerWarp.isEnabled();
}
/**
* Gets the PlayerWarp object
*
* @return the PlayerWarp object
*/
public PlayerWarp getPlayerWarp() {
return playerWarp;
}
/**
* Gets the location of the toggled warp
*
* @return the location of the warp
*/
public Location getLocation() {
return playerWarp.getLocation();
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -1,10 +1,7 @@
package world.bentobox.warps.listeners;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@ -25,10 +22,13 @@ import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.events.addon.AddonEvent;
import world.bentobox.bentobox.api.events.flags.FlagProtectionChangeEvent;
import world.bentobox.bentobox.api.events.team.TeamKickEvent;
import world.bentobox.bentobox.api.events.team.TeamLeaveEvent;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.util.Util;
import world.bentobox.warps.objects.PlayerWarp;
import world.bentobox.warps.Warp;
import world.bentobox.warps.event.WarpRemoveEvent;
@ -61,18 +61,18 @@ public class WarpSignsListener implements Listener {
@Override
public void run() {
boolean changed = false;
Iterator<Map.Entry<UUID, Location>> iterator =
Iterator<Map.Entry<UUID, PlayerWarp>> iterator =
addon.getWarpSignsManager().getWarpMap(event.getWorld()).entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<UUID, Location> entry = iterator.next();
Map.Entry<UUID, PlayerWarp> entry = iterator.next();
UUID uuid = entry.getKey();
Location location = entry.getValue();
Location location = entry.getValue().getLocation();
if (event.getChunk().getX() == location.getBlockX() >> 4
&& event.getChunk().getZ() == location.getBlockZ() >> 4
&& !Tag.SIGNS.isTagged(location.getBlock().getType())) {
iterator.remove();
// Remove sign from warp panel cache
addon.getWarpPanelManager().removeWarp(event.getWorld(), uuid);
addon.getSignCacheManager().removeWarp(event.getWorld(), uuid);
changed = true;
}
}
@ -114,7 +114,6 @@ public class WarpSignsListener implements Listener {
return;
}
User user = User.getInstance(e.getPlayer());
if (user == null) return;
UUID owner = addon.getWarpSignsManager().getWarpOwnerUUID(b.getLocation()).orElse(null);
if (isPlayersSign(e.getPlayer(), b, inWorld)) {
addon.getWarpSignsManager().removeWarp(b.getLocation());
@ -128,16 +127,16 @@ public class WarpSignsListener implements Listener {
private boolean isPlayersSign(Player player, Block b, boolean inWorld) {
// Welcome sign detected - check to see if it is this player's sign
Map<UUID, Location> list = addon.getWarpSignsManager().getWarpMap(b.getWorld());
Map<UUID, PlayerWarp> list = addon.getWarpSignsManager().getWarpMap(b.getWorld());
String reqPerm = inWorld ? addon.getPermPrefix(b.getWorld()) + "mod.removesign" : Warp.WELCOME_WARP_SIGNS + ".mod.removesign";
return ((list.containsKey(player.getUniqueId()) && list.get(player.getUniqueId()).equals(b.getLocation()))
return ((list.containsKey(player.getUniqueId()) && list.get(player.getUniqueId()).getLocation().equals(b.getLocation()))
|| player.isOp() || player.hasPermission(reqPerm));
}
private boolean isWarpSign(Block b) {
Sign s = (Sign) b.getState();
return s.getLine(0).equalsIgnoreCase(ChatColor.GREEN + addon.getSettings().getWelcomeLine())
&& addon.getWarpSignsManager().getWarpMap(b.getWorld()).containsValue(s.getLocation());
&& addon.getWarpSignsManager().getWarpMap(b.getWorld()).values().stream().anyMatch(playerWarp -> playerWarp.getLocation().equals(s.getLocation()));
}
/**
@ -160,12 +159,24 @@ public class WarpSignsListener implements Listener {
if (noPerms(user, b.getWorld(), inWorld)) {
return;
}
// TODO: These checks are useless if the sign is placed outside a BSB world.
// This will mean level and rank requirements are nil in the case of allow-in-other-worlds: true.
// I'm not sure if there is a better way around this without adding new API checking for primary
// or last island accessed with relevant permissions.
// ignored.
if (inWorld && noLevelOrIsland(user, b.getWorld())) {
e.setLine(0, ChatColor.RED + addon.getSettings().getWelcomeLine());
return;
}
if (inWorld && !hasCorrectIslandRank(b, user)) {
e.setLine(0, ChatColor.RED + addon.getSettings().getWelcomeLine());
user.sendMessage("warps.error.not-correct-rank");
return;
}
// Check if the player already has a sign
final Location oldSignLoc = addon.getWarpSignsManager().getWarp(b.getWorld(), user.getUniqueId());
final Location oldSignLoc = addon.getWarpSignsManager().getWarpLocation(b.getWorld(), user.getUniqueId());
if (oldSignLoc != null) {
// A sign already exists. Check if it still there and if
// so,
@ -192,6 +203,46 @@ public class WarpSignsListener implements Listener {
}
private boolean hasCorrectIslandRank(Block b, User user) {
final Optional<Island> islandOpt = plugin.getIslands().getIslandAt(b.getLocation());
if(islandOpt.isEmpty()) return false;
final Island island = islandOpt.get();
final int userRank = island.getRank(user);
return userRank >= island.getFlag(addon.getCreateWarpFlag());
}
@EventHandler
public void onFlagChange(FlagProtectionChangeEvent e) {
if(!e.getEditedFlag().equals(addon.getCreateWarpFlag())) return;
if(!addon.getSettings().getRemoveExistingWarpsWhenFlagChanges()) return;
final Island island = e.getIsland();
final Map<UUID, PlayerWarp> islandWarps = addon
.getWarpSignsManager()
.getWarpMap(island.getWorld())
.entrySet()
.stream()
.filter(x -> island.inIslandSpace(x.getValue().getLocation()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
for(Map.Entry<UUID, PlayerWarp> entry : islandWarps.entrySet()) {
if(island.getRank(entry.getKey()) >= e.getSetTo()) continue;
//The user has a lower rank than the new set value.
//We need to remove the warp.
addon.getWarpSignsManager().removeWarp(island.getWorld(), entry.getKey());
if(Bukkit.getPlayer(entry.getKey()) != null) {
Objects.requireNonNull(User.getInstance(entry.getKey())).sendMessage(WARPS_DEACTIVATE);
}
}
}
private boolean noLevelOrIsland(User user, World world) {
// Get level if level addon is available
Long level = addon.getLevel(Util.getWorld(world), user.getUniqueId());

View File

@ -1,4 +1,4 @@
package world.bentobox.warps;
package world.bentobox.warps.managers;
import java.util.List;

View File

@ -1,4 +1,4 @@
package world.bentobox.warps;
package world.bentobox.warps.managers;
import java.util.HashMap;
import java.util.Map;
@ -10,6 +10,7 @@ import org.bukkit.World;
import org.eclipse.jdt.annotation.NonNull;
import world.bentobox.bentobox.database.Database;
import world.bentobox.warps.Warp;
import world.bentobox.warps.objects.SignCache;
public class SignCacheManager {
@ -36,7 +37,7 @@ public class SignCacheManager {
});
}
void saveCache() {
public void saveCache() {
cachedSigns.forEach((w, m) -> handler.saveObjectAsync(new SignCache(w, m)));
}
@ -47,7 +48,7 @@ public class SignCacheManager {
* @return SignCacheItem
*/
@NonNull
SignCacheItem getSignItem(World world, UUID warpOwner) {
public SignCacheItem getSignItem(World world, UUID warpOwner) {
// Add the worlds if we haven't seen this before
cachedSigns.putIfAbsent(world, new HashMap<>());
// Get from cache if available
@ -70,7 +71,7 @@ public class SignCacheManager {
* @param key - uuid of owner
* @return true if item is removed from cache
*/
boolean removeWarp(World world, UUID key) {
public boolean removeWarp(World world, UUID key) {
if (cachedSigns.containsKey(world)) {
return cachedSigns.get(world).remove(key) != null;
}

View File

@ -1,4 +1,4 @@
package world.bentobox.warps;
package world.bentobox.warps.managers;
import java.util.ArrayList;
import java.util.Arrays;
@ -21,13 +21,12 @@ import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.Tag;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Sign;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
@ -38,8 +37,13 @@ import world.bentobox.bentobox.database.Database;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.lists.Flags;
import world.bentobox.bentobox.util.Util;
import world.bentobox.warps.objects.PlayerWarp;
import world.bentobox.warps.Warp;
import world.bentobox.warps.event.WarpCreateEvent;
import world.bentobox.warps.event.WarpInitiateEvent;
import world.bentobox.warps.objects.WarpsData;
import world.bentobox.warps.panels.Utils;
/**
* Handles warping. Players can add one sign
@ -52,7 +56,7 @@ public class WarpSignsManager {
private static final String WARPS = "warps";
private final BentoBox plugin;
// Map of all warps stored as player, warp sign Location
private Map<World, Map<UUID, Location>> worldsWarpList;
private Map<World, Map<UUID, PlayerWarp>> worldsWarpList;
// Database handler for level data
private final Database<WarpsData> handler;
@ -65,7 +69,7 @@ public class WarpSignsManager {
* @return map of warps
*/
@NonNull
public Map<UUID, Location> getWarpMap(@Nullable World world) {
public Map<UUID, PlayerWarp> getWarpMap(@Nullable World world) {
return worldsWarpList.computeIfAbsent(Util.getWorld(world), k -> new HashMap<>());
}
@ -97,13 +101,15 @@ public class WarpSignsManager {
return false;
}
// Check for warps placed in a location where there was a warp before
if (getWarpMap(loc.getWorld()).containsValue(loc)) {
// remove the warp at this location, then place it
for (PlayerWarp playerWarp : getWarpMap(loc.getWorld()).values()) {
if (playerWarp.getLocation().equals(loc)) {
this.removeWarp(loc);
break;
}
getWarpMap(loc.getWorld()).put(playerUUID, loc);
}
getWarpMap(loc.getWorld()).put(playerUUID, new PlayerWarp(loc, true));
saveWarpList();
Bukkit.getPluginManager().callEvent(new WarpInitiateEvent(addon, loc, playerUUID));
Bukkit.getPluginManager().callEvent(new WarpCreateEvent(addon, loc, playerUUID));
return true;
}
@ -116,7 +122,13 @@ public class WarpSignsManager {
* @return Location of warp or null
*/
@Nullable
public Location getWarp(World world, UUID playerUUID) {
public Location getWarpLocation(World world, UUID playerUUID) {
PlayerWarp playerWarp = getWarpMap(world).get(playerUUID);
return playerWarp != null ? playerWarp.getLocation() : null;
}
@Nullable
public PlayerWarp getPlayerWarp(World world, UUID playerUUID) {
return getWarpMap(world).get(playerUUID);
}
@ -127,7 +139,7 @@ public class WarpSignsManager {
*/
@NonNull
public String getWarpOwner(Location location) {
return getWarpMap(location.getWorld()).entrySet().stream().filter(en -> en.getValue().equals(location))
return getWarpMap(location.getWorld()).entrySet().stream().filter(en -> en.getValue().getLocation().equals(location))
.findFirst().map(en -> plugin.getPlayers().getName(en.getKey())).orElse("");
}
@ -137,7 +149,7 @@ public class WarpSignsManager {
* @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))
return getWarpMap(location.getWorld()).entrySet().stream().filter(en -> en.getValue().getLocation().equals(location))
.findFirst().map(Map.Entry::getKey);
}
@ -151,12 +163,16 @@ public class WarpSignsManager {
return r;
}
List<UUID> processWarpMap(CompletableFuture<List<UUID>> r, @NonNull World world) {
public 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
getWarpMap(world).values().removeIf(Objects::isNull);
// Bigger value of time means a more recent login
TreeMap<Long, UUID> map = new TreeMap<>();
getWarpMap(world).forEach((uuid, value) -> {
// If the warp is not enabled, skip this iteration
if (!value.isEnabled()) {
return;
}
// If never played, will be zero
long lastPlayed = addon.getServer().getOfflinePlayer(uuid).getLastPlayed();
// This aims to avoid the chance that players logged off at exactly the same time
@ -185,28 +201,33 @@ public class WarpSignsManager {
public Set<UUID> listWarps(@NonNull World world) {
// Remove any null locations
getWarpMap(world).values().removeIf(Objects::isNull);
return getWarpMap(world).entrySet().stream().filter(e -> Util.sameWorld(world, Objects.requireNonNull(e.getValue().getWorld()))).map(Map.Entry::getKey).collect(Collectors.toSet());
// Remove any warps that have not been toggled on
Map<UUID, PlayerWarp> enabledWarps = getWarpMap(world).entrySet().stream()
.filter(entry -> entry.getValue().isEnabled())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
return enabledWarps.keySet();
}
/**
* Load the warps and check if they still exist
*/
void loadWarpList() {
public void loadWarpList() {
addon.log("Loading warps...");
worldsWarpList = new HashMap<>();
if (handler.objectExists(WARPS)) {
warpsData = handler.loadObject(WARPS);
// Load into map
if (warpsData != null) {
warpsData.getWarpSigns().forEach((k,v) -> {
if (k != null && k.getWorld() != null) {
if (k.getWorld().isChunkLoaded(k.getBlockX() >> 4, k.getBlockZ() >> 4)
&& !k.getBlock().getType().name().contains("SIGN")) {
warpsData.getWarpSigns().forEach((pw, uuid) -> {
Location location = pw.getLocation();
if (location != null && location.getWorld() != null) {
if (location.getWorld().isChunkLoaded(location.getBlockX() >> 4, location.getBlockZ() >> 4)
&& !location.getBlock().getType().name().contains("SIGN")) {
return;
}
// Add to map
getWarpMap(k.getWorld()).put(v, k);
getWarpMap(location.getWorld()).put(uuid, new PlayerWarp(location, true));
}
});
} else {
@ -237,16 +258,16 @@ public class WarpSignsManager {
*/
public void removeWarp(Location loc) {
popSign(loc);
Iterator<Entry<UUID, Location>> it = getWarpMap(loc.getWorld()).entrySet().iterator();
Iterator<Entry<UUID, PlayerWarp>> it = getWarpMap(loc.getWorld()).entrySet().iterator();
while (it.hasNext()) {
Entry<UUID, Location> en = it.next();
if (en.getValue().equals(loc)) {
Entry<UUID, PlayerWarp> en = it.next();
if (en.getValue().getLocation().equals(loc)) {
// Inform player
Optional.ofNullable(addon.getServer().getPlayer(en.getKey()))
.map(User::getInstance)
.ifPresent(user -> user.sendMessage("warps.sign-removed"));
// Remove sign from warp panel cache
addon.getWarpPanelManager().removeWarp(loc.getWorld(), en.getKey());
addon.getSignCacheManager().removeWarp(loc.getWorld(), en.getKey());
it.remove();
}
}
@ -260,12 +281,12 @@ public class WarpSignsManager {
*/
public void removeWarp(World world, UUID uuid) {
if (getWarpMap(world).containsKey(uuid)) {
popSign(getWarpMap(world).get(uuid));
popSign(getWarpMap(world).get(uuid).getLocation());
getWarpMap(world).remove(uuid);
}
// Remove sign from warp panel cache
addon.getWarpPanelManager().removeWarp(world, uuid);
addon.getSignCacheManager().removeWarp(world, uuid);
saveWarpList();
}
@ -283,7 +304,7 @@ public class WarpSignsManager {
*/
public void saveWarpList() {
handler.saveObjectAsync(warpsData.save(worldsWarpList));
addon.getWarpPanelManager().saveCache();
addon.getSignCacheManager().saveCache();
}
/**
@ -296,7 +317,7 @@ public class WarpSignsManager {
@NonNull
public SignCacheItem getSignInfo(@NonNull World world, @NonNull UUID uuid) {
//get the sign info
Location signLocation = getWarp(world, uuid);
Location signLocation = getWarpLocation(world, uuid);
if (signLocation == null || !signLocation.getBlock().getType().name().contains("SIGN")) {
return new SignCacheItem();
}
@ -311,7 +332,6 @@ public class WarpSignsManager {
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;
@ -319,20 +339,21 @@ public class WarpSignsManager {
if (!prefix.isEmpty())
{
icon = Material.matchMaterial(
this.getPermissionValue(Objects.requireNonNull(User.getInstance(uuid)),
prefix + "island.warp",
this.addon.getSettings().getIcon()));
Utils.getPermissionValue(User.getInstance(uuid), prefix + "island.warp",
Material.OAK_SIGN.name()));
}
else
{
icon = Material.matchMaterial(this.addon.getSettings().getIcon());
icon = null;
}
if (icon == null || icon.name().contains("SIGN")) {
if (icon != null && icon.name().contains("SIGN")) {
return new SignCacheItem(result, Material.valueOf(sign.getType().name().replace("WALL_", "")));
}
else
{
return new SignCacheItem(result, icon);
}
}
/**
@ -348,7 +369,19 @@ public class WarpSignsManager {
float yaw = Util.blockFaceToFloat(directionFacing);
final Location actualWarp = new Location(inFront.getWorld(), inFront.getBlockX() + 0.5D, inFront.getBlockY(),
inFront.getBlockZ() + 0.5D, yaw, 30F);
Util.teleportAsync(user.getPlayer(), actualWarp, TeleportCause.COMMAND);
WarpInitiateEvent e = new WarpInitiateEvent(addon, actualWarp, user.getUniqueId());
Bukkit.getPluginManager().callEvent(e);
if (e.isCancelled()) {
return;
}
//BentoBox prevents people from teleporting to an island when
//the user is banned from the island for example.
//By checking if the teleport succeeded before sending the messages,
//we prevent issues where no one teleported, but people still
//get messages about it.
Util.teleportAsync(user.getPlayer(), actualWarp, TeleportCause.COMMAND).thenAccept(tpResult -> {
if(Boolean.FALSE.equals(tpResult)) return;
User warpOwner = Objects.requireNonNull(User.getInstance(signOwner));
// Hide invisible players
if (warpOwner.isOnline() && !warpOwner.getPlayer().canSee(user.getPlayer())) {
@ -361,8 +394,13 @@ public class WarpSignsManager {
user.getWorld().playSound(Objects.requireNonNull(user.getLocation()), Sound.ENTITY_BAT_TAKEOFF, 1F, 1F);
}
if (!warpOwner.equals(user)) {
warpOwner.sendMessage("warps.player-warped", "[name]", user.getName());
final String gameMode = BentoBox
.getInstance()
.getIWM()
.getFriendlyName(actualWarp.getWorld());
warpOwner.sendMessage("warps.player-warped", "[name]", user.getName(), "[gamemode]", gameMode);
}
});
}
/**
@ -373,7 +411,7 @@ public class WarpSignsManager {
* @param owner - owner of the warp
*/
public void warpPlayer(@NonNull World world, @NonNull User user, @NonNull UUID owner) {
final Location warpSpot = getWarp(world, owner);
final Location warpSpot = getWarpLocation(world, owner);
// Check if the warp spot is safe
if (warpSpot == null) {
user.sendMessage("warps.error.does-not-exist");
@ -410,7 +448,7 @@ public class WarpSignsManager {
}
// Find out which direction the warp is facing
Block b = warpSpot.getBlock();
if (b.getType().name().contains("WALL_SIGN")) {
if (Tag.WALL_SIGNS.isTagged(b.getType())) {
org.bukkit.block.data.type.WallSign s = (org.bukkit.block.data.type.WallSign) b.getBlockData();
BlockFace directionFacing = s.getFacing();
Location inFront = b.getRelative(directionFacing).getLocation();
@ -423,7 +461,13 @@ public class WarpSignsManager {
warpPlayer(user, oneDown, owner, directionFacing, pvp);
return;
}
} else if (b.getType().name().contains("SIGN")) {
} else if (Tag.ALL_HANGING_SIGNS.isTagged(b.getType())) {
Location below = b.getRelative(BlockFace.DOWN).getRelative(BlockFace.DOWN).getLocation();
if ((addon.getIslands().isSafeLocation(below))) {
warpPlayer(user, below, owner, BlockFace.DOWN, pvp);
return;
}
} else if (Tag.STANDING_SIGNS.isTagged(b.getType())) {
org.bukkit.block.data.type.Sign s = (org.bukkit.block.data.type.Sign) b.getBlockData();
BlockFace directionFacing = s.getRotation();
Location inFront = b.getRelative(directionFacing).getLocation();
@ -460,54 +504,4 @@ public class WarpSignsManager {
public boolean hasWarp(@NonNull World world, @NonNull UUID playerUUID) {
return getWarpMap(world).containsKey(playerUUID);
}
// ---------------------------------------------------------------------
// Section: Other methods
// ---------------------------------------------------------------------
/**
* This method gets string value of given permission prefix. If user does not have
* given permission or it have all (*), then return default value.
* @param user User who's permission should be checked.
* @param permissionPrefix Prefix that need to be found.
* @param defaultValue Default value that will be returned if permission not found.
* @return String value that follows permissionPrefix.
*/
private String getPermissionValue(@NonNull User user, @NonNull String permissionPrefix, @NonNull String defaultValue)
{
if (user.isPlayer())
{
if (permissionPrefix.endsWith("."))
{
permissionPrefix = permissionPrefix.substring(0, permissionPrefix.length() - 1);
}
String permPrefix = permissionPrefix + ".";
List<String> permissions = user.getEffectivePermissions().stream()
.map(PermissionAttachmentInfo::getPermission)
.filter(permission -> permission.startsWith(permPrefix))
.toList();
for (String permission : permissions)
{
if (permission.contains(permPrefix + "*"))
{
// * means all. So continue to search more specific.
continue;
}
String[] parts = permission.split(permPrefix);
if (parts.length > 1)
{
return parts[1];
}
}
}
return defaultValue;
}
}

View File

@ -0,0 +1,32 @@
package world.bentobox.warps.objects;
import com.google.gson.annotations.Expose;
import org.bukkit.Location;
import java.io.Serializable;
public class PlayerWarp implements Serializable {
@Expose
private final Location location;
@Expose
private boolean isEnabled;
public PlayerWarp(Location location, boolean isEnabled) {
this.location = location;
this.isEnabled = isEnabled;
}
public Location getLocation() {
return location;
}
public boolean isEnabled() {
return isEnabled;
}
public void toggle() {
isEnabled = !isEnabled;
}
}

View File

@ -10,7 +10,7 @@ import com.google.gson.annotations.Expose;
import world.bentobox.bentobox.database.objects.DataObject;
import world.bentobox.bentobox.database.objects.Table;
import world.bentobox.warps.SignCacheItem;
import world.bentobox.warps.managers.SignCacheItem;
@Table(name = "WarpSignCache")
public class SignCache implements DataObject {

View File

@ -17,9 +17,13 @@ public class WarpsData implements DataObject {
@Expose
private String uniqueId = "warps";
@Expose
@Deprecated @Expose
private Map<Location, UUID> warpSigns = new HashMap<>();
@Expose
private Map<PlayerWarp, UUID> newWarpSigns = new HashMap<>();
public WarpsData() {
// Required by YAML database
}
@ -34,24 +38,40 @@ public class WarpsData implements DataObject {
this.uniqueId = uniqueId;
}
public Map<Location, UUID> getWarpSigns() {
if (warpSigns == null)
public Map<PlayerWarp, UUID> getWarpSigns() {
convertOldWarpSigns();
if (newWarpSigns == null)
return new HashMap<>();
return warpSigns;
}
public void setWarpSigns(Map<Location, UUID> warpSigns) {
this.warpSigns = warpSigns;
return newWarpSigns;
}
/**
* Puts all the data from the map into this objects ready for saving
* Method for converting old warp signs to new warp signs
*/
public void convertOldWarpSigns() {
if (warpSigns == null) {
return;
}
for (Map.Entry<Location, UUID> entry : warpSigns.entrySet()) {
PlayerWarp playerWarp = new PlayerWarp(entry.getKey(), true);
newWarpSigns.put(playerWarp, entry.getValue());
}
warpSigns = null;
}
public void setWarpSigns(Map<PlayerWarp, UUID> warpSigns) {
this.newWarpSigns = warpSigns;
}
/**
* Puts all the data from the map into these objects ready for saving
* @param worldsWarpList 2D map of warp locations by world vs UUID
* @return this class filled with data
*/
public WarpsData save(Map<World, Map<UUID, Location>> worldsWarpList) {
public WarpsData save(Map<World, Map<UUID, PlayerWarp>> worldsWarpList) {
getWarpSigns().clear();
worldsWarpList.values().forEach(world -> world.forEach((uuid,location) -> warpSigns.put(location, uuid)));
worldsWarpList.values().forEach(world -> world.forEach((uuid,playerWarp) -> newWarpSigns.put(playerWarp, uuid)));
return this;
}

View File

@ -0,0 +1,76 @@
//
// Created by BONNe
// Copyright - 2021
//
package world.bentobox.warps.panels;
import org.bukkit.permissions.PermissionAttachmentInfo;
import java.util.List;
import java.util.stream.Collectors;
import world.bentobox.bentobox.api.user.User;
public class Utils
{
/**
* This method sends a message to the user with appended "prefix" text before message.
* @param user User who receives message.
* @param translationText Translation text of the message.
* @param parameters Parameters for the translation text.
*/
public static void sendMessage(User user, String translationText, String... parameters)
{
user.sendMessage(user.getTranslation( "warps.conversations.prefix") +
user.getTranslation( translationText, parameters));
}
/**
* This method gets string value of given permission prefix. If user does not have given permission or it have all
* (*), then return default value.
*
* @param user User who's permission should be checked.
* @param permissionPrefix Prefix that need to be found.
* @param defaultValue Default value that will be returned if permission not found.
* @return String value that follows permissionPrefix.
*/
public static String getPermissionValue(User user, String permissionPrefix, String defaultValue)
{
if (user.isPlayer())
{
if (permissionPrefix.endsWith("."))
{
permissionPrefix = permissionPrefix.substring(0, permissionPrefix.length() - 1);
}
String permPrefix = permissionPrefix + ".";
List<String> permissions = user.getEffectivePermissions().stream().
map(PermissionAttachmentInfo::getPermission).
filter(permission -> permission.startsWith(permPrefix)).
toList();
for (String permission : permissions)
{
if (permission.contains(permPrefix + "*"))
{
// * means all. So continue to search more specific.
continue;
}
String[] parts = permission.split(permPrefix);
if (parts.length > 1)
{
return parts[1];
}
}
}
return defaultValue;
}
}

View File

@ -0,0 +1,598 @@
//
// Created by BONNe
// Copyright - 2021
//
package world.bentobox.warps.panels;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import java.io.File;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.TemplatedPanel;
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
import world.bentobox.bentobox.api.panels.builders.TemplatedPanelBuilder;
import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.warps.managers.SignCacheItem;
import world.bentobox.warps.managers.SignCacheManager;
import world.bentobox.warps.Warp;
/**
* This class shows how to set up easy panel by using BentoBox PanelBuilder API
*/
public class WarpsPanel
{
// ---------------------------------------------------------------------
// Section: Constructor
// ---------------------------------------------------------------------
/**
* This is internal constructor. It is used internally in current class to avoid creating objects everywhere.
*
* @param addon VisitAddon object
* @param world World where user will be teleported
* @param user User who opens panel
*/
private WarpsPanel(Warp addon,
World world,
User user)
{
this.addon = addon;
this.manager = this.addon.getSignCacheManager();
this.user = user;
this.world = world;
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* This method collects and validates sign warps that could be displayed in GUI.
* @param completed CompletableFeature that triggers panel opening.
*/
private void collectValidWarps(CompletableFuture<Boolean> completed)
{
this.addon.getWarpSignsManager().getSortedWarps(this.world).
thenAccept(warps ->
{
// Cache and clean the signs
Iterator<UUID> iterator = warps.iterator();
while (iterator.hasNext())
{
UUID warpOwner = iterator.next();
@NonNull
SignCacheItem sign = this.manager.getSignItem(this.world, warpOwner);
if (!sign.isReal())
{
iterator.remove();
this.addon.getWarpSignsManager().removeWarpFromMap(this.world, warpOwner);
}
}
// Assign warps to element list.
this.elementList = warps;
// Build the main body
completed.complete(true);
});
}
/**
* This is wrapper around builder to trigger main GUI building.
*/
private void initBuild()
{
CompletableFuture<Boolean> collectWarps = new CompletableFuture<>();
this.collectValidWarps(collectWarps);
collectWarps.thenAccept(done -> {
if (done)
{
this.build();
}
});
}
/**
* Build method manages current panel opening. It uses BentoBox PanelAPI that is easy to use and users can get nice
* panels.
*/
private void build()
{
// Do not open gui if there is no magic sticks.
if (this.elementList.isEmpty())
{
this.addon.logError("There are no available islands for visiting!");
Utils.sendMessage(this.user, "warps.error.no-warps-yet",
"[gamemode]", this.addon.getPlugin().getIWM().getAddon(this.world).
map(gamemode -> gamemode.getDescription().getName()).
orElse(""));
return;
}
// Start building panel.
TemplatedPanelBuilder panelBuilder = new TemplatedPanelBuilder();
// Set main template.
panelBuilder.template("warps_panel", new File(this.addon.getDataFolder(), "panels"));
panelBuilder.user(this.user);
panelBuilder.world(this.user.getWorld());
// Register button builders
panelBuilder.registerTypeBuilder("WARP", this::createWarpButton);
panelBuilder.registerTypeBuilder("RANDOM", this::createRandomButton);
// Register next and previous builders
panelBuilder.registerTypeBuilder("NEXT", this::createNextButton);
panelBuilder.registerTypeBuilder("PREVIOUS", this::createPreviousButton);
// Register unknown type builder.
panelBuilder.build();
}
// ---------------------------------------------------------------------
// Section: Buttons
// ---------------------------------------------------------------------
/**
* Create next button panel item.
*
* @param template the template
* @param slot the slot
* @return the panel item
*/
@Nullable
private PanelItem createNextButton(@NonNull ItemTemplateRecord template, TemplatedPanel.ItemSlot slot)
{
int size = this.elementList.size();
if (size <= slot.amountMap().getOrDefault("WARP", 1) ||
1.0 * size / slot.amountMap().getOrDefault("WARP", 1) <= this.pageIndex + 1)
{
// There are no next elements
return null;
}
int nextPageIndex = this.pageIndex + 2;
PanelItemBuilder builder = new PanelItemBuilder();
if (template.icon() != null)
{
ItemStack clone = template.icon().clone();
if ((Boolean) template.dataMap().getOrDefault("indexing", false))
{
clone.setAmount(nextPageIndex);
}
builder.icon(clone);
}
if (template.title() != null)
{
builder.name(this.user.getTranslation(this.world, template.title()));
}
if (template.description() != null)
{
builder.description(this.user.getTranslation(this.world, template.description(),
"[number]", String.valueOf(nextPageIndex)));
}
// Add ClickHandler
builder.clickHandler((panel, user, clickType, i) ->
{
template.actions().forEach(action -> {
if (clickType == action.clickType() || action.clickType() == ClickType.UNKNOWN)
{
if ("NEXT".equalsIgnoreCase(action.actionType()))
{
// Next button ignores click type currently.
this.pageIndex++;
this.build();
}
}
});
// Always return true.
return true;
});
// Collect tooltips.
List<String> tooltips = template.actions().stream().
filter(action -> action.tooltip() != null).
map(action -> this.user.getTranslation(this.world, action.tooltip())).
filter(text -> !text.isBlank()).
collect(Collectors.toCollection(() -> new ArrayList<>(template.actions().size())));
// Add tooltips.
if (!tooltips.isEmpty())
{
// Empty line and tooltips.
builder.description("");
builder.description(tooltips);
}
return builder.build();
}
/**
* Create previous button panel item.
*
* @param template the template
* @param slot the slot
* @return the panel item
*/
@Nullable
private PanelItem createPreviousButton(@NonNull ItemTemplateRecord template, TemplatedPanel.ItemSlot slot)
{
if (this.pageIndex == 0)
{
// There are no next elements
return null;
}
int previousPageIndex = this.pageIndex;
PanelItemBuilder builder = new PanelItemBuilder();
if (template.icon() != null)
{
ItemStack clone = template.icon().clone();
if ((Boolean) template.dataMap().getOrDefault("indexing", false))
{
clone.setAmount(previousPageIndex);
}
builder.icon(clone);
}
if (template.title() != null)
{
builder.name(this.user.getTranslation(this.world, template.title()));
}
if (template.description() != null)
{
builder.description(this.user.getTranslation(this.world, template.description(),
"[number]", String.valueOf(previousPageIndex)));
}
// Add ClickHandler
// Add ClickHandler
builder.clickHandler((panel, user, clickType, i) ->
{
template.actions().forEach(action -> {
if (clickType == action.clickType() || action.clickType() == ClickType.UNKNOWN)
{
if ("PREVIOUS".equalsIgnoreCase(action.actionType()))
{
// Next button ignores click type currently.
this.pageIndex--;
this.build();
}
}
});
// Always return true.
return true;
});
// Collect tooltips.
List<String> tooltips = template.actions().stream().
filter(action -> action.tooltip() != null).
map(action -> this.user.getTranslation(this.world, action.tooltip())).
filter(text -> !text.isBlank()).
collect(Collectors.toCollection(() -> new ArrayList<>(template.actions().size())));
// Add tooltips.
if (!tooltips.isEmpty())
{
// Empty line and tooltips.
builder.description("");
builder.description(tooltips);
}
return builder.build();
}
/**
* This method creates and returns warp button.
*
* @return PanelItem that represents warp button.
*/
@Nullable
private PanelItem createWarpButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot)
{
if (this.elementList.isEmpty())
{
// Does not contain any sticks.
return null;
}
int index = this.pageIndex * slot.amountMap().getOrDefault("WARP", 1) + slot.slot();
if (index >= this.elementList.size())
{
// Out of index.
return null;
}
return this.createWarpButton(template, this.elementList.get(index), "warp");
}
/**
* This method creates and returns random warp button.
*
* @return PanelItem that represents random warp button.
*/
@Nullable
private PanelItem createRandomButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot)
{
if (this.elementList.size() < 2)
{
// Does not contain any sticks.
return null;
}
int index = random.nextInt(this.elementList.size());
return this.createWarpButton(template, this.elementList.get(index), "random");
}
// ---------------------------------------------------------------------
// Section: Other methods
// ---------------------------------------------------------------------
/**
* This method creates and returns button that switch to next page in view mode.
*
* @return PanelItem that allows to select next owner view page.
*/
private PanelItem createWarpButton(ItemTemplateRecord template, UUID ownerUUID, String type)
{
if (ownerUUID == null)
{
// return as owner has no owner. Empty button will be created.
return null;
}
SignCacheItem signCache = this.manager.getSignItem(this.world, ownerUUID);
if (!signCache.isReal())
{
this.addon.getWarpSignsManager().removeWarpFromMap(this.world, ownerUUID);
// return as signCache is not real anymore.
return null;
}
final String reference = "warps.gui.buttons." + type + ".";
String ownerName = addon.getPlugin().getPlayers().getName(ownerUUID);
// Get settings for owner.
PanelItemBuilder builder = new PanelItemBuilder();
if (template.icon() != null)
{
if (template.icon().getType().equals(Material.PLAYER_HEAD))
{
builder.icon(ownerName);
}
else
{
builder.icon(template.icon().clone());
}
}
else
{
// Check owner for a specific icon
Material material = signCache.getType();
if (material == null)
{
// Set oak sign as icon was not specified.
material = Material.OAK_SIGN;
}
if (material == Material.PLAYER_HEAD)
{
builder.icon(ownerName);
}
else
{
builder.icon(material);
}
}
if (template.title() != null)
{
builder.name(this.user.getTranslation(this.world, template.title(),
"[name]", ownerName));
}
else
{
builder.name(this.user.getTranslation(reference + "name",
"[name]", ownerName));
}
// Process Description of the button.
// Generate [sign_text] text
String descriptionText;
if (template.description() != null)
{
descriptionText = this.user.getTranslationOrNothing(template.description(),
"[name]", ownerName,
"[sign_text]", String.join("\n", signCache.getSignText())).
replaceAll("(?m)^[ \\t]*\\r?\\n", "").
replaceAll("(?<!\\\\)\\|", "\n").
replaceAll("\\\\\\|", "|");
}
else
{
descriptionText = this.user.getTranslationOrNothing(reference + "description",
"[name]", ownerName,
"[sign_text]", String.join("|", signCache.getSignText()));
// Clean up description text and split it into parts.
descriptionText = descriptionText.replaceAll("(?m)^[ \\t]*\\r?\\n", "").
replaceAll("(?<!\\\\)\\|", "\n").
replaceAll("\\\\\\|", "|");
}
builder.description(descriptionText);
// Add ClickHandler
builder.clickHandler((panel, user, clickType, i) ->
{
template.actions().forEach(action -> {
if (clickType == action.clickType() || action.clickType() == ClickType.UNKNOWN)
{
if ("WARP".equalsIgnoreCase(action.actionType()))
{
this.runCommandCall(ownerName);
}
}
});
// Always return true.
return true;
});
// Collect tooltips.
List<String> tooltips = template.actions().stream().
filter(action -> action.tooltip() != null).
map(action -> this.user.getTranslation(this.world, action.tooltip())).
filter(text -> !text.isBlank()).
collect(Collectors.toCollection(() -> new ArrayList<>(template.actions().size())));
// Add tooltips.
if (!tooltips.isEmpty())
{
// Empty line and tooltips.
builder.description("");
builder.description(tooltips);
}
return builder.build();
}
/**
* This method runs command call that allows player to visit clicked island.
*/
private void runCommandCall(String ownerName)
{
// Get first player command label.
String command = this.addon.getSettings().getWarpCommand().split(" ")[0];
String gamemodeCommand = this.addon.getPlugin().getIWM().getAddon(this.world).
map(gamemode -> gamemode.getPlayerCommand().map(Command::getLabel).orElse("")).
orElse("");
if (gamemodeCommand.isEmpty())
{
this.addon.log(this.user.getName() + " called: `" + command + " " + ownerName + "`");
this.user.performCommand(command + " " + ownerName);
}
else
{
this.addon.log(this.user.getName() + " called: `" + gamemodeCommand + " " + command + " " + ownerName + "`");
this.user.performCommand(gamemodeCommand + " " + command + " " + ownerName);
}
// Close inventory
this.user.closeInventory();
}
// ---------------------------------------------------------------------
// Section: Static methods
// ---------------------------------------------------------------------
/**
* This method is used to open UserPanel outside this class. It will be much easier to open panel with single method
* call then initializing new object.
*
* @param addon Warps object
* @param world World where user will be teleported
* @param user User who opens panel
*/
public static void openPanel(Warp addon,
World world,
User user)
{
new WarpsPanel(addon, world, user).initBuild();
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This variable allows to access addon object.
*/
private final Warp addon;
/**
* This variable allows to access addon manager object.
*/
private final SignCacheManager manager;
/**
* This variable holds user who opens panel. Without it panel cannot be opened.
*/
private final User user;
/**
* This variable holds world where panel is opened. Without it panel cannot be opened.
*/
private final World world;
/**
* This variable stores filtered elements.
*/
private List<UUID> elementList;
/**
* This variable holds current pageIndex for multi-page island choosing.
*/
private int pageIndex;
/**
* Random for finding random warp.
*/
private static final Random random = new Random();
}

View File

@ -10,8 +10,14 @@ softdepend: AcidIsland, BSkyBlock, CaveBlock, SkyGrid, AOneBlock
permissions:
'[gamemode].island.warp':
description: Player can use warp or warps commands
description: Player can use warp command
default: true
'[gamemode].island.warps':
description: Player can use the warps command
default: true
'[gamemode].island.addwarp':
description: Player can create a welcome warp sign
default: true
'[gamemode].island.togglewarp':
description: Player can toggle a warp sign
default: true

View File

@ -8,36 +8,29 @@
# 0 or negative values will disable this restriction 10 is default
warplevelrestriction: 10
#
# Should warps be removed when the island protection settings
# change, and the owner of the warp does no longer have
# the correct rank
removeExistingWarpsWhenFlagChanges: true
#
# Text that player must put on sign to make it a warp sign
# Not case sensitive!
welcomeLine: '[Welcome]'
#
# Icon that will be displayed in Warps list. SIGN counts for any kind of sign and the type of
# wood used will be reflected in the panel if the server supports it.
# It uses native Minecraft material strings, but using string 'PLAYER_HEAD', it is possible to
# use player heads instead. Beware that Mojang API rate limiting may prevent heads from loading.
icon: 'SIGN'
#
# This list stores GameModes in which Level addon should not work.
# To disable addon it is necessary to write its name in new line that starts with -. Example:
# disabled-gamemodes:
# - BSkyBlock
disabled-gamemodes: []
#
# Warp panel name formatting.
# Example: &c will make names red, &f is white
name-format: "&f"
#
# Warp panel default lore formatting.
# Example: &c will make lore red. &f is white
lore-format: "&f"
#
# Allow random teleport - adds a button to the warp panel that goes to a random warp sign
random-allowed: true
#
# Allow use in other worlds. Players must have the welcomewarpsigns.warp permission.
allow-in-other-worlds: false
#
# Warp and warps commands. You can change them if they clash with other addons or plugins.
warp-command: warp
warps-command: warps
togglewarp-command: togglewarp

View File

@ -1,30 +1,46 @@
#
# 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: Warpt dich zu dem Warp Schild von dem Spieler
parameters: <Spielername>
parameters: "<player name>"
warps:
deactivate: '&c Altes Warp Schild deaktiviert!'
deactivate: "&c Altes Warp Schild deaktiviert!"
error:
does-not-exist: '&c Oh nein! Dieser Warp existiert nicht mehr!'
no-permission: '&c Hierfür hast du keine Rechte!'
no-remove: '&c Du kannst dieses Schild nicht entfernen!'
no-warps-yet: '&c Es sind noch keine Warps verfügbar'
not-enough-level: '&c Dein Insel-Level ist nicht hoch gneug!'
not-on-island: '&c Dafür musst du auf deiner Insel sein!'
not-safe: '&c Dieser Warp ist nicht sicher!'
your-level-is: '&c Dein Insel-Level ist erst [level] und muss höher als [required] sein.
Nutze das Level Kommando.'
does-not-exist: "&c Oh nein! Dieser Warp existiert nicht mehr!"
no-permission: "&c Hierfür hast du keine Rechte!"
no-remove: "&c Du kannst dieses Schild nicht entfernen!"
no-warps-yet: "&c Es sind noch keine Warps verfügbar"
not-enough-level: "&c Dein Insel-Level ist nicht hoch gneug!"
not-on-island: "&c Dafür musst du auf deiner Insel sein!"
not-safe: "&c Dieser Warp ist nicht sicher!"
your-level-is: "&c Dein Insel-Level ist erst [level] und muss höher als [required]
sein. Nutze das Level Kommando."
help:
description: Öffnet das Warps Panel
next: '&6 Nächste Seite'
player-warped: '&2 [name] hat sich zu deinem Warp Schild gewarpt!'
previous: '&6 Vorherige Seite'
random: '&4 Zufälliger Warp'
sign-removed: '&c Warp Schild entfernt!'
success: '&a Erfolg!'
title: Warp Schilder
warpTip: '&6 Platziere ein Warp Schild mit [text] in der ersten Zeile'
warpToPlayersSign: '&6 Warpe zu [player]''s Schild'
player-warped: "&2 [name] hat sich zu deinem Warp Schild gewarpt!"
sign-removed: "&c Warp Schild entfernt!"
success: "&a Erfolg!"
warpTip: "&6 Platziere ein Warp Schild mit [text] in der ersten Zeile"
warpToPlayersSign: "&6 Warpe zu [player]'s Schild"
gui:
titles:
warp-title: "&0&l Warp-Schild"
buttons:
previous:
name: "&f&l Vorherige Seite"
description: "&7 Zur Seite [number] wechseln"
next:
name: "&f&l Nächste Seite"
description: "&7 Zur Seite [number] wechseln"
warp:
name: "&f&l [name]"
description: "[sign_text]"
random:
name: "&f&l Random Warp"
description: "&7 Hmm, wo werde ich erscheinen?"
tips:
click-to-previous: "&e Klicken &7, um die vorherige Seite anzuzeigen."
click-to-next: "&e Klicken &7, um die nächste Seite anzuzeigen."
click-to-warp: "&e Zum Warpen &7 klicken."
conversations:
prefix: "&l&6 [BentoBox]: &r"

View File

@ -18,16 +18,60 @@ warps:
not-on-island: "&c You must be on your island to do that!"
not-safe: "&c That warp is not safe!"
your-level-is: "&c Your island level is only [level] and must be higher than [required]. Run the level command."
not-correct-rank: "&c You do not have the correct rank to set a warp!"
help:
description: "open the warps panel"
next: "&6 Next page"
player-warped: "&2 [name] warped to your warp sign!"
previous: "&6 Previous page"
random: "&4 Random Warp"
player-warped: "&2 [name] warped to your [gamemode] warp sign!"
sign-removed: "&c Warp sign removed!"
success: "&a Success!"
title: "Warp Signs"
warpTip: "&6 Place a warp sign with [text] on the top"
warpToPlayersSign: "&6 Warping to [player]'s sign"
gui:
titles:
# The title of warp panel
warp-title: '&0&l Warp Signs'
buttons:
# Button that is used in multi-page GUIs which allows to return to previous page.
previous:
name: "&f&l Previous Page"
description: |-
&7 Switch to [number] page
# Button that is used in multi-page GUIs which allows to go to next page.
next:
name: "&f&l Next Page"
description: |-
&7 Switch to [number] page
# Button for a warp
warp:
name: "&f&l [name]"
description: |-
[sign_text]
# Button for a random warp
random:
name: "&f&l Random Warp"
description: |-
&7 Hmm, where will I appear?
tips:
click-to-previous: "&e Click &7 to view previous page."
click-to-next: "&e Click &7 to view next page."
click-to-warp: "&e Click &7 to warp."
conversations:
# Prefix for messages that are send from server.
prefix: "&l&6 [BentoBox]: &r"
togglewarp:
help:
description: "toggle the warp sign"
enabled: "&a Your warp is now visible!"
disabled: "&c Your warp is now hidden!"
error:
no-permission: "&c You do not have permission to do that!"
generic: "&c An error occurred while toggling your warp."
no-warp: "&c You do not have a warp to toggle!"
protection:
flags:
PLACE_WARP:
name: Place Warp
description: Allow placing warp sign

View File

@ -1,31 +1,53 @@
###########################################################################################################
# Este es un archivo YML. Tenga cuidado al editar. Revisa tus ediciones en un verificador de YAML como #
# el de http://yaml-online-parser.appspot.com #
###########################################################################################################
---
warp:
help:
description: "Teletransportarte hacia el warp del jugador"
parameters: <player name>
description: Teletransportarte hacia el warp del jugador
parameters: "<player name>"
warps:
deactivate: "&c¡El cartel viejo ha sido desactivado!"
deactivate: "&c ¡Antiguo cartel de teletransportación desactivado!"
error:
does-not-exist: "&c¡Oh vaya! !Ese warp ya no existe!"
no-permission: "&c¡No tienes permiso para hacer eso!"
does-not-exist: "&c ¡Oh, chasquido! ¡Ese teletransporte ya no existe!"
no-permission: "&c ¡No tienes permisos para hacer eso!"
no-remove: "&c ¡No puedes quitar ese cartel!"
no-warps-yet: "&cNo hay warps disponibles aún"
no-warps-yet: "&c No hay teletransportes disponibles todavía"
not-enough-level: "&c ¡Tu nivel de isla no es lo suficientemente alto!"
not-on-island: "&c ¡Debes estar en tu isla para hacer eso!"
not-safe: "&c¡Ese warp no es seguro!"
your-level-is: "&cTu nivel de isla es solo [level] y debe ser mayor que [required]"
not-safe: "&c ¡Ese teletransporte no es seguro!"
your-level-is: "&c Tu nivel de isla es solo [level] y debe ser mayor que [required].
Ejecuta el comando de nivel."
not-correct-rank: "&c ¡No tienes el rango correcto para crear un teletransporte!"
help:
description: "Abre el panel de warps"
next: "&6Siguiente página"
player-warped: "&2[name] ¡se ha teletransportado a tu warp!"
previous: "&6Página anterior"
random: "&4Teletransporte aleatorio"
sign-removed: "&c¡Cartel removido!"
success: "&a¡Éxito!"
title: "Carteles de Warps"
warpTip: "&6Coloca un cartel que contenga el texto [text] arriba"
warpToPlayersSign: "&6Teletransportandote al warp de [player]"
description: Abre el panel de warps
player-warped: "&2 [name] se ha teletransportado a tu cartel de teletransportación
de [gamemode]!"
sign-removed: "&c Cartel de teletransportación eliminado!"
success: "&a Éxito!"
warpTip: "&6 Coloca un cartel con [text] en la parte superior"
warpToPlayersSign: "&6 Teletransportandote al cartel del jugador [player]"
gui:
titles:
warp-title: "&0&l Carteles de Teletransporte"
buttons:
previous:
name: "&f&l Página Anterior"
description: "&7 Ir a la página [number]"
next:
name: "&f&l Siguiente Página"
description: "&7 Ir a la página [number]"
warp:
name: "&f&l [name]"
description: "[sign_text]"
random:
name: "&f&l Teletransporte aleatorio"
description: "&7 Hmm, ¿Dónde apareceré?"
tips:
click-to-previous: "&e Clic &7 para ver la página anterior."
click-to-next: "&e Clic &7 para ver la página siguiente."
click-to-warp: "&e Clic &7 para teletransportarse."
conversations:
prefix: "&l&6 [BentoBox]: &r"
protection:
flags:
PLACE_WARP:
name: Colocar Teletransporte
description: Permitir colocar un cartel de teletransporte

View File

@ -4,25 +4,50 @@ warp:
description: te téléporte au Warp d'un autre joueur
parameters: "<pseudo>"
warps:
deactivate: "&cAncien panneau de Warp désactivé !"
deactivate: "&c Ancienne pancarte de warp désactivée !"
error:
does-not-exist: "&cCe Warp n'existe plus !"
no-permission: "&cVous n'avez pas la permission pour faire cela !"
no-remove: "&cVous ne pouvez pas supprimer ce panneau !"
not-enough-level: "&cVotre niveau d'île n'est pas assez élevé pour faire cela
!"
does-not-exist: "&c Oh ! Cette téléportation n'existe plus !"
no-permission: "&c Vous n'avez pas le droit de faire cela !"
no-remove: "&c Vous ne pouvez pas enlever cette pancarte !"
no-warps-yet: "&c Il n'y a pas encore de téléportation disponible"
not-enough-level: "&c Le niveau de votre île n'est pas assez élevé !"
not-on-island: "&c Vous devez être sur votre île pour faire cela !"
not-safe: "&cCe Warp n'est pas sûr!"
no-warps-yet: "&cIl n'y a encore aucun Warp sur ce serveur."
your-level-is: "&cVotre île est seulement niveau [level] et doit être niveau [required]."
not-safe: "&c Cette téléportation n'est pas sûre !"
your-level-is: "&c Le niveau de votre île n'est que [level] et doit être supérieur
à [required]. Exécutez la commande level."
not-correct-rank: "&c Vous n'avez pas le grade adéquat pour poser une chaîne !"
help:
description: Ouvre le menu des Warps
next: "&6Page suivante"
player-warped: "&2[name] s'est téléporté sur votre île !"
previous: "&6Page précédente"
sign-removed: "&cPanneau de Warp supprimé !"
player-warped: "&2 [name] s'est rendu à votre pancarte de téléportation [gamemode]
!"
sign-removed: "&c Panneau de téléportation enlevé !"
success: "&a Succès !"
title: Panneau Warp
warpTip: "&6Placez un panneau et écrivez [text] sur la première ligne."
warpToPlayersSign: "&6Téléportation sur l'île de [player]..."
random: "&4Warp aléatoire"
warpTip: "&6 Placer une pancarte de téléportation avec [text] sur le dessus"
warpToPlayersSign: "&6 Téléportation a la pancarte de [player]"
gui:
titles:
warp-title: "&0&l Pancarte de téléportation"
buttons:
previous:
name: "&f&l Page précédente"
description: "&7 Aller à la page [numéro]."
next:
name: "&f&l Page suivante"
description: "&7 Passer à la page [numéro]."
warp:
name: "&f&l [name]"
description: "[sign_text]"
random:
name: "&f&l Téléportation aléatoire"
description: "&7 Hmm, où vais-je apparaître ?"
tips:
click-to-previous: "&e Cliquez sur &7 pour afficher la page précédente."
click-to-next: "&e Cliquez sur &7 pour afficher la page suivante."
click-to-warp: "&e Cliquez sur &7 pour te téléporter."
conversations:
prefix: "&l&6 [BentoBox]: &r"
protection:
flags:
PLACE_WARP:
name: Place téléportation
description: Autoriser le placement d'un panneau téléportation

View File

@ -1,12 +1,8 @@
###########################################################################################
# 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: "Teleportálás a játékos teleport táblájához"
parameters: <player name>
description: Teleportálás a játékos teleport táblájához
parameters: "<játékosnév>"
warps:
deactivate: "&cRégi teleport tábla deaktiválva!"
error:
@ -17,17 +13,16 @@ warps:
not-enough-level: "&cA szigeted szintje nem elég magas!"
not-on-island: "&cEhhez szigeten kell lenned!"
not-safe: "&cEz a teleport nem biztonságos!"
your-level-is: "&cJelenleg a sziget szinted [level], és nagyobbnak kell lennie, mint [required]."
your-level-is: "&cJelenleg a sziget szinted [level], és nagyobbnak kell lennie,
mint [required]."
help:
description: "Teleportok panel megnyitása"
description: Teleportok panel megnyitása
next: "&6Következő oldal"
player-warped: "&2[name] teleportált a teleport tábládhoz!"
previous: "&6Előző oldal"
random: "&4Véletlenszerű Teleport"
sign-removed: "&cTeleport tábla törölve!"
success: "&aSikeres!"
title: "Teleport Táblák"
title: Teleport Táblák
warpTip: "&6Helyezz le egy teleport táblát a következő szöveggel [text] a tetején"
warpToPlayersSign: "&6Teleportálás [player] táblájához"

View File

@ -0,0 +1,52 @@
---
warp:
help:
description: warp ke tanda warp pemain
parameters: "<player name>"
warps:
deactivate: "&c Tanda warp lama dinonaktifkan!"
error:
does-not-exist: "&c Oh! Warp itu tidak ada lagi!"
no-permission: "&c Kamu tidak punya izin untuk melakukan itu!"
no-remove: "&c Kamu tidak bisa menghapus tanda itu!"
no-warps-yet: "&c Belum ada warps yang tersedia"
not-enough-level: "&c Level pulaumu tidak cukup tinggi!"
not-on-island: "&c Kamu harus berada di pulaumu untuk melakukan itu!"
not-safe: "&c Warp itu tidak aman!"
your-level-is: "&c Level pulau Anda hanya [level] dan harus lebih tinggi dari
[required]. Jalankan perintah level."
not-correct-rank: "&c Kamu tidak punya rank yang benar untuk mengatur warp!"
help:
description: buka panel warps
player-warped: "&2 [name] nge-warp ke tanda warp [gamemode] kamu!"
sign-removed: "&c Tanda warp dihilangkan!"
success: "&a Sukses!"
warpTip: "&6 Tempatkan tanda warp dengan [text] di atas\n"
warpToPlayersSign: "&6 Pergi ke tanda [player]"
gui:
titles:
warp-title: "&0&l Tanda Warp"
buttons:
previous:
name: "&f&l Halaman Sebelumnya"
description: "&7 Beralih ke halaman [number]"
next:
name: "&f&l Halaman Selanjutnya"
description: "&7 Beralih ke halaman [number]"
warp:
name: "&f&l [name]"
description: "[sign_text]"
random:
name: "&f&l Warp Acak"
description: "&7 Hmm, di mana aku akan muncul?"
tips:
click-to-previous: "&e Klik &7 untuk melihat halaman sebelumnya."
click-to-next: "&e Klik &7 untuk melihat halaman selanjutnya."
click-to-warp: "&e Klik &7 untuk warp."
conversations:
prefix: "&l&6 [BentoBox]: &r"
protection:
flags:
PLACE_WARP:
name: Tempatkan Warp
description: Izinkan menempatkan tanda warp

View File

@ -0,0 +1,29 @@
---
warp:
help:
description: teletrasporto al cartello Warp del giocatore
parameters: "<nome giocatore>"
warps:
deactivate: "&c Vecchio cartello Warp disattivato!"
error:
does-not-exist: "&c Quel cartello Warp non esiste più!"
no-permission: "&c Non hai i permessi per farlo!"
no-remove: "&c Non puoi rimuovere quel cartello!"
no-warps-yet: "&c Non ci sono ancora Warp disponibili"
not-enough-level: "&c Il tuo livello dell'isola non è abbastanza alto!"
not-on-island: "&c Devi essere nella tua isola per farlo!"
not-safe: "&c Il Warp non è sicuro!"
your-level-is: "&c Il tuo livello dell''isola è solo di [level] e deve essere
maggiore di [required]. Esegui il comando del calcolo dei livelli per aggiornare
il livello."
help:
description: apri il pannello dei Warp
next: "&6 Pagina Successiva"
player-warped: "&2 [name] teletrasportato al tuo cartello Warp!"
previous: "&6 Pagina Precedente"
random: "&4 Warp Random"
sign-removed: "&c Cartello Warp rimosso!"
success: "&a Successo!"
title: Cartelli Warp
warpTip: "&6 Piazza un cartello Warp con [text] scritto nella prima riga"
warpToPlayersSign: "&6 Teletrasporto al cartello Warp di [player]"

View File

@ -0,0 +1,52 @@
---
warp:
help:
description: teleporteer naar een speler zijn warp bord
parameters: "<speler>"
warps:
deactivate: "&c Oude warp bord is gedeactiveerd!"
error:
does-not-exist: "&c Oh nee! Deze warp bestaat niet meer!"
no-permission: "&c Je hebt geen permissies om dit te doen!"
no-remove: "&c Je kan dit bord niet weghalen!"
no-warps-yet: "&c Er bestaan nog geen warps op dit moment"
not-enough-level: "&c Je eiland level is nog niet hoog genoeg!"
not-on-island: "&c Je moet een eiland hebben om dit te doen!"
not-safe: "&c Deze warp is niet veilig!"
your-level-is: "&c Je eiland level is [level], maar het moet op zijn minst [required]
zijn. Gebruik het level commando."
not-correct-rank: "&c Je hebt niet de correcte rank om een warp te maken!"
help:
description: open het warp paneel
player-warped: "&2 [name] teleporteerde naar jou [gamemode] warp!"
sign-removed: "&c Warp bord verwijderd!"
success: "&a Geslaagd!"
warpTip: "&6 Plaats een warp bord met [text] op de eerste regel"
warpToPlayersSign: "&6 Teleporteren naar [player]'s warp"
gui:
titles:
warp-title: "&0&l Warp Borden"
buttons:
previous:
name: "&f&l Vorige pagina"
description: "&7 Ga naar pagina [number]"
next:
name: "&f&l Volgende pagina"
description: "&7 Ga naar pagina [number]"
warp:
name: "&f&l [name]"
description: "[sign_text]"
random:
name: "&f&l Willekeurige Warp"
description: "&7 Hmm, waar ga ik heen?"
tips:
click-to-previous: "&e Klik &7 om naar de vorige pagina te gaan."
click-to-next: "&e Klik &7 om naar de volgende pagina te gaan."
click-to-warp: "&e Klik &7 om te teleporteren."
conversations:
prefix: "&l&6 [BentoBox]: &r"
protection:
flags:
PLACE_WARP:
name: Plaats warp
description: Staat het toe om een warp bord te plaatsen

View File

@ -1,27 +1,46 @@
---
warp:
help:
description: teleportuje cię do tabliczki innego gracza
parameters: <gracz>
parameters: "<gracz>"
warps:
deactivate: '&c Stary teleport zdezaktywowany!'
deactivate: "&c Stary teleport został zdezaktywowany!"
error:
does-not-exist: '&c Ten teleport nie istnieje.'
no-permission: '&c Brak uprawnień!'
no-remove: '&c Nie możesz usunąć tej tabliczki!'
no-warps-yet: '&c Nie ma jeszcze teleportów.'
not-enough-level: '&c Twój poziom wyspy nie jest wystarczająco wysoki!'
not-on-island: '&c Musisz być na wyspie, by to zrobić.'
not-safe: '&c Ten teleport nie jest bezpieczny!'
your-level-is: '&c Twój poziom wyspy to [level], a musi wynosić co namniej [required].
Użyj komendy /is level.'
does-not-exist: "&c Ten teleport nie istnieje."
no-permission: "&c Brak uprawnień!"
no-remove: "&c Nie możesz usunąć tej tabliczki!"
no-warps-yet: "&c Nie ma jeszcze stworzonych teleportów."
not-enough-level: "&c Twój poziom wyspy nie jest wystarczająco wysoki!"
not-on-island: "&c Musisz być na wyspie, by to zrobić."
not-safe: "&c Ten teleport nie jest bezpieczny!"
your-level-is: "&c Twój poziom wyspy to [level], a musi wynosić co najmniej [required].
Użyj komendy /is level."
help:
description: otwiera panel warpów
next: '&6 Następna strona'
player-warped: '&2 [name] teleportował się do twojej tabliczki!'
previous: '&6 Poprzednia strona'
random: '&4 Losowy teleport'
sign-removed: '&c Usunięto tabliczkę!'
success: '&a Sukces!'
title: Tabliczki teleportacyjne
warpTip: '&6 Postaw tabliczkę z napisem [text]'
warpToPlayersSign: '&6 Teleportowanie do tabliczki gracza [player]'
player-warped: "&2 [name] teleportował się do twojej tabliczki!"
sign-removed: "&c Usunięto tabliczkę!"
success: "&a Sukces!"
warpTip: "&6 Postaw tabliczkę z napisem [text]"
warpToPlayersSign: "&6 Teleportowanie do tabliczki gracza [player]"
gui:
titles:
warp-title: "&0&l Lista dostępnych wysp"
buttons:
previous:
name: "&f&l Poprzednia strona"
description: "&7 Przełącz na stronę [number]"
next:
name: "&f&l następna strona"
description: "&7 Przełącz na stronę [number]"
warp:
name: "&f&l [name]"
description: "[sign_text]"
random:
name: "&f&l Losowa wyspa"
description: "&7 Hmm, gdzie się pojawię?"
tips:
click-to-previous: "&e Kliknij &7, aby wyświetlić poprzednią stronę."
click-to-next: "&e Kliknij &7, aby wyświetlić następną stronę."
click-to-warp: "&e Kliknij &7, aby przenieść."
conversations:
prefix: "&l&6 [BentoBox]: &r"

View File

@ -8,20 +8,19 @@ warps:
error:
does-not-exist: "&cÜzgünüm. Böyle bir bölge artık yok!"
no-permission: "&4Buna yetkin yok!"
not-safe: "&4Ada bölgesi güvenli değil!"
no-remove: "&4Bu tabelayı kıramazsın!"
no-warps-yet: "&4Böyle bir bölge henüz yok."
not-enough-level: "&4Bunu koyman için daha fazla ada leveline ihtiyacın var."
not-on-island: "&4Adanda değilsin."
not-safe: "&4Ada bölgesi güvenli değil!"
your-level-is: "&9Ada levelin &e[level] &9ve &e[required]&9'den fazla olması gerek!"
help:
description: Bölge panelini açar.
next: "&6Sonraki Sayfa"
player-warped: "&d[name] &9ada bölgene ışınlandı!"
previous: "&6Önceki sayfa"
random: "&4Rastgele bölgeye git!"
sign-removed: "&4Ada tabelası kaldırıldı!"
success: "&aBaşarılı!"
title: "&dOyuncu bölgeleri &8- &5"
warpTip: "&6Ada bölgesi açmak için tabelanın en üstüne &a[text] &9yaz!"
warpToPlayersSign: "&d[player] &9bölgesine gidiliyor!"
next: "&6Sonraki Sayfa"
previous: "&6Önceki sayfa"
random: "&4Rastgele bölgeye git!"

View File

@ -0,0 +1,52 @@
---
warp:
help:
description: телепортація на знак варпа гравця
parameters: "<player name>"
warps:
deactivate: "&c Старий знак варпу деактивовано!"
error:
does-not-exist: "&c О, чорт! Того викривлення більше не існує!"
no-permission: "&c Ви не маєте на це дозволу!"
no-remove: "&c Ви не можете видалити цей знак!"
no-warps-yet: "&c Ще немає доступних варпів"
not-enough-level: "&c Рівень вашого острова недостатньо високий!"
not-on-island: "&c Для цього ви повинні бути на своєму острові!"
not-safe: "&c Ця варп небезпечна!"
your-level-is: "&c Рівень вашого острова становить лише [level] і має бути вищим
за [required]. Виконайте команду рівня."
not-correct-rank: "&c Ви не маєте належного рангу, щоб встановити варп!"
help:
description: відкрити панель варпів
player-warped: "&2 [name] телепортовано до вашого знака варпу [gamemode]!"
sign-removed: "&c Знак варпу видалено!"
success: "&a Успіх!"
warpTip: "&6 Розмістіть знак варпу з [text] угорі"
warpToPlayersSign: "&6 Телепортація на знак [player]."
gui:
titles:
warp-title: "&0&l Знаки варпів"
buttons:
previous:
name: "&f&l Попередня сторінка"
description: "&7 Перейти на сторінку [number]."
next:
name: "&f&l Наступна сторінка"
description: "&7 Перейти на сторінку [number]."
warp:
name: "&f&l [name]"
description: "[sign_text]"
random:
name: "&f&l Випадковий варп"
description: "&7 Хм, а де я з'явлюся?"
tips:
click-to-previous: "&e Натисніть &7, щоб переглянути попередню сторінку."
click-to-next: "&e Натисніть &7, щоб переглянути наступну сторінку."
click-to-warp: "&e Натисніть &7, щоб деформувати."
conversations:
prefix: "&l&6 [BentoBox]: &r"
protection:
flags:
PLACE_WARP:
name: Розмістіть варп
description: Дозволити розміщення варпів

View File

@ -1,27 +1,60 @@
---
# ##########################################################################################
# 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: 传送到该玩家的传送木牌处
parameters: "<player name>"
description: 传送至对应玩家的坐标告示牌
parameters: <player name>
warps:
help:
description: 打开传送面板
title: 传送木牌
deactivate: "&c 旧传送牌已停用!"
deactivate: '&c检测到不活跃的坐标告示牌!'
error:
does-not-exist: "&c 哦不!那个传送点已经没了!"
no-permission: "&c 你无权那样做!"
no-remove: "&c 你拿不掉那个牌子的!"
no-warps-yet: "&c 暂无可用传送点"
not-enough-level: "&c 你的岛等级不够高!"
not-on-island: "&c 你得在自己的岛屿上操作!"
not-safe: "&c 目标传送点不安全!"
your-level-is: "&c 你的岛现在 [level] 级,需要 [required] 级。 试试岛屿等级命令吧。"
next: "&6 次页"
player-warped: "&2 [name] 传送到了你的传送牌!"
previous: "&6 前页"
random: "&4 随机传送"
sign-removed: "&c 拆掉传送牌了!"
success: "&a 成了!"
warpTip: "&6 放个牌子第一行写 [text]"
warpToPlayersSign: "&6 正传送到 [player] 的牌子"
does-not-exist: '&c啊哦! 那个传送点已经不存在了!'
no-permission: '&c你没有权限做这件事!'
no-remove: '&c你不能移除该告示牌!'
no-warps-yet: '&c尚无可用传送点.'
not-enough-level: '&c你空岛的等级还不够高!'
not-on-island: '&c你必须在自己的空岛上做这件事!'
not-safe: '&c该传送点不安全!'
your-level-is: '&c你空岛的等级只有[level], 但必须高于[required]. 使用/is level查看等级.'
not-correct-rank: '&c你在团队中的地位不足以让你设立传送点!'
help:
description: 打开传送点面板
player-warped: '&2 [name]传送到了你[gamemode]的坐标告示牌!'
sign-removed: '&c坐标告示牌已移除!'
success: '&a成功!'
warpTip: '&6放置一个顶部为[text]的坐标告示牌'
warpToPlayersSign: '&6正在传送至[player]的坐标告示牌'
gui:
titles:
# The title of warp panel
warp-title: '&0&l坐标告示牌'
buttons:
# Button that is used in multi-page GUIs which allows to return to previous page.
previous:
name: '&f&l上一页'
description: '&7跳转到第[number]页' # Button that is used in multi-page GUIs which allows to go to next page.
next:
name: '&f&l下一页'
description: '&7跳转到第[number]页' # Button for a warp
warp:
name: '&f&l [name]'
description: '[sign_text]' # Button for a random warp
random:
name: '&f&l随机传送'
description: '&7嗯...我会出现在哪里?'
tips:
click-to-previous: '&e点击&7 查看上一页.'
click-to-next: '&e点击&7 查看下一页.'
click-to-warp: '&e点击&7 进行传送.'
conversations:
# Prefix for messages that are send from server.
prefix: '&l&6 [BentoBox]: &r'
protection:
flags:
PLACE_WARP:
name: 放置传送点
description: 允许放置坐标告示牌

View File

@ -0,0 +1,27 @@
---
warp:
help:
description: 傳送到該玩家的傳送木牌處
parameters: "<player name>"
warps:
deactivate: "&c 舊傳送牌已停用!"
error:
does-not-exist: "&c 哦不!那個傳送點已經沒了!"
no-permission: "&c 你沒有權限這樣做!"
no-remove: "&c 你拿不掉那個牌子的!"
no-warps-yet: "&c 暫無可用傳送點"
not-enough-level: "&c 你的島嶼等級不夠高!"
not-on-island: "&c 你得在自己的島嶼上操作!"
not-safe: "&c 目標傳送點不安全!"
your-level-is: "&c 你的島嶼現在 [level] 級,需要 [required] 級。 試試島嶼等級命令吧。"
help:
description: 打開傳送面板
next: "&6 下一頁"
player-warped: "&2 [name] 傳送到了你的傳送牌!"
previous: "&6 上一頁"
random: "&4 隨機傳送"
sign-removed: "&c 拆掉傳送牌了!"
success: "&成功!"
title: 傳送告示牌
warpTip: "&6 放個牌子第一行寫 [text] "
warpToPlayersSign: "&6 正傳送到 [player] 的牌子"

View File

@ -0,0 +1,79 @@
warps_panel:
title: warps.gui.titles.warp-title
type: INVENTORY
background:
icon: BLACK_STAINED_GLASS_PANE
title: "&b&r" # Empty text
border:
icon: BLACK_STAINED_GLASS_PANE
title: "&b&r" # Empty text
force-shown: []
content:
2:
2: warp_button
3: warp_button
4: warp_button
5: warp_button
6: warp_button
7: warp_button
8: warp_button
3:
1:
icon: tipped_arrow{CustomPotionColor:11546150}
title: warps.gui.buttons.previous.name
description: warps.gui.buttons.previous.description
data:
type: PREVIOUS
indexing: true
actions:
left:
type: PREVIOUS
tooltip: warps.gui.tips.click-to-previous
2: warp_button
3: warp_button
4: warp_button
5: warp_button
6: warp_button
7: warp_button
8: warp_button
9:
icon: tipped_arrow{CustomPotionColor:8439583}
title: warps.gui.buttons.next.name
description: warps.gui.buttons.next.description
data:
type: NEXT
indexing: true
actions:
left:
type: NEXT
tooltip: warps.gui.tips.click-to-next
4:
2: warp_button
3: warp_button
4: warp_button
5: warp_button
6: warp_button
7: warp_button
8: warp_button
6:
5:
icon: DROPPER
title: warps.gui.buttons.random.name
description: warps.gui.buttons.random.description
data:
type: RANDOM
actions:
warp:
click-type: left
tooltip: warps.gui.tips.click-to-warp
reusable:
warp_button:
icon: PLAYER_HEAD
title: warps.gui.buttons.warp.name
description: warps.gui.buttons.warp.description
data:
type: WARP
actions:
warp:
click-type: left
tooltip: warps.gui.tips.click-to-warp

View File

@ -1,8 +1,9 @@
name: Pladdon
name: BentoBox-Warps
main: world.bentobox.warps.WarpsPladdon
version: ${version}
api-version: 1.16
description: A Warp Pladdon for BentoBox
author: tastybento
depend:
- BentoBox
version: ${project.version}${build.number}
api-version: "1.17"
authors: [tastybento]
contributors: ["The BentoBoxWorld Community"]
website: https://bentobox.world
description: ${project.description}

View File

@ -1,329 +0,0 @@
package world.bentobox.warps;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
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.when;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFactory;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.scheduler.BukkitScheduler;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.AbstractDatabaseHandler;
import world.bentobox.bentobox.database.DatabaseSetup;
import world.bentobox.bentobox.managers.PlayersManager;
import world.bentobox.warps.config.Settings;
/**
* @author tastybento
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({Bukkit.class, DatabaseSetup.class})
public class WarpPanelManagerTest {
@Mock
private WarpSignsManager wsm;
@Mock
private Warp addon;
@Mock
private Player player;
@Mock
private User user;
@Mock
private World world;
@Mock
private Inventory top;
@Mock
private Settings settings;
@Mock
private static AbstractDatabaseHandler<Object> handler;
@Mock
private BukkitScheduler scheduler;
private List<UUID> list;
// Class under test
private WarpPanelManager wpm;
@SuppressWarnings("unchecked")
@BeforeClass
public static void beforeClass() {
// This has to be done beforeClass otherwise the tests will interfere with each other
handler = mock(AbstractDatabaseHandler.class);
// Database
PowerMockito.mockStatic(DatabaseSetup.class);
DatabaseSetup dbSetup = mock(DatabaseSetup.class);
when(DatabaseSetup.getDatabase()).thenReturn(dbSetup);
when(dbSetup.getHandler(any())).thenReturn(handler);
}
/**
*/
@Before
public void setUp() {
when(addon.getWarpSignsManager()).thenReturn(wsm);
// Fill with 200 fake warps (I'm banking on them all being different, but there could be a clash)
list = new ArrayList<>();
for (int i = 0; i< 200; i++) {
list.add(UUID.randomUUID());
}
// One final one
UUID uuid = UUID.randomUUID();
list.add(uuid);
when(wsm.getSortedWarps(any())).thenReturn(CompletableFuture.completedFuture(list));
// User and player
when(user.getPlayer()).thenReturn(player);
when(user.getTranslation(any())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class));
// BentoBox
BentoBox plugin = mock(BentoBox.class);
PlayersManager pm = mock(PlayersManager.class);
when(pm.getName(any())).thenReturn("name");
when(plugin.getPlayers()).thenReturn(pm);
when(addon.getPlugin()).thenReturn(plugin);
// Bukkit
PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
ItemFactory itemF = mock(ItemFactory.class);
ItemMeta imeta = mock(ItemMeta.class);
when(itemF.getItemMeta(any())).thenReturn(imeta);
when(Bukkit.getItemFactory()).thenReturn(itemF);
when(Bukkit.getScheduler()).thenReturn(scheduler);
// Inventory
when(top.getSize()).thenReturn(9);
when(Bukkit.createInventory(any(), anyInt(), any())).thenReturn(top);
when(settings.getIcon()).thenReturn("SIGN");
when(addon.getSettings()).thenReturn(settings);
Location location = mock(Location.class);
Block block = mock(Block.class);
Material signType;
try {
signType = Material.valueOf("SIGN");
} catch (Exception e) {
signType = Material.valueOf("OAK_SIGN");
}
when(block.getType()).thenReturn(signType);
when(location.getBlock()).thenReturn(block);
// Sign block
when(wsm.getWarp(any(), any())).thenReturn(location);
// Sign cache
SignCacheItem sc = new SignCacheItem(Collections.singletonList("[welcome]"), signType);
when(wsm.getSignInfo(any(), any())).thenReturn(sc);
// Class under test
wpm = new WarpPanelManager(addon);
}
/**
* Test method for {@link WarpPanelManager#processSigns(CompletableFuture, PanelBuilder, User, int, World)}.
*/
@Test
public void testShowWarpPanelTestCache() {
PanelBuilder pb = mock(PanelBuilder.class);
// Do initial lookups of sign text
wpm.processSigns(new CompletableFuture<>(), pb, user, 3, world);
// Get the panel again
wpm.processSigns(new CompletableFuture<>(), pb, user, 3, world);
// Should only check this 201 times in total because the sign text is cached
verify(wsm, times(201)).getSignInfo(any(), any());
}
/**
* Test method for {@link WarpPanelManager#removeWarp(org.bukkit.World, java.util.UUID)}.
*/
@Test
public void testRemoveWarp() {
assertFalse(wpm.removeWarp(world, UUID.randomUUID()));
}
/**
* Test method for {@link WarpPanelManager#buildPanel(PanelBuilder, User, int, World)}
*/
@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

@ -8,7 +8,9 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
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.when;
@ -21,11 +23,11 @@ import java.util.concurrent.CompletableFuture;
import java.util.logging.Logger;
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.Tag;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Block;
@ -40,6 +42,7 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
@ -60,15 +63,20 @@ import world.bentobox.bentobox.managers.PlaceholdersManager;
import world.bentobox.bentobox.managers.PlayersManager;
import world.bentobox.bentobox.util.Util;
import world.bentobox.warps.config.Settings;
import world.bentobox.warps.event.WarpCreateEvent;
import world.bentobox.warps.event.WarpInitiateEvent;
import world.bentobox.warps.managers.SignCacheManager;
import world.bentobox.warps.managers.WarpSignsManager;
import world.bentobox.warps.objects.PlayerWarp;
import world.bentobox.warps.objects.WarpsData;
/**
* @author tastybento
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({Bukkit.class, Util.class, DatabaseSetup.class, ChatColor.class})
@PrepareForTest({Bukkit.class, Util.class, DatabaseSetup.class})
public class WarpSignsManagerTest {
@Mock
@ -98,7 +106,7 @@ public class WarpSignsManagerTest {
@Mock
private Player player;
@Mock
private WarpPanelManager wpm;
private SignCacheManager wpm;
@Mock
private PlayersManager pm;
@Mock
@ -136,12 +144,15 @@ public class WarpSignsManagerTest {
// Player
when(player.getUniqueId()).thenReturn(uuid);
when(player.isOnline()).thenReturn(true);
when(player.canSee(any(Player.class))).thenReturn(true);
User.setPlugin(plugin);
User.getInstance(player);
// Locales
LocalesManager lm = mock(LocalesManager.class);
when(lm.get(Mockito.any(), Mockito.any())).thenReturn(null);
when(lm.getAvailablePrefixes(any())).thenReturn(Collections.emptySet());
when(lm.get(Mockito.any(), Mockito.any())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(1, String.class));
when(plugin.getLocalesManager()).thenReturn(lm);
// Return the same string
PlaceholdersManager phm = mock(PlaceholdersManager.class);
@ -185,7 +196,7 @@ public class WarpSignsManagerTest {
// Handler
when(handler.objectExists("warps")).thenReturn(true);
Map<Location, UUID> warpMap = Collections.singletonMap(location, uuid);
Map<PlayerWarp, UUID> warpMap = Collections.singletonMap(new PlayerWarp(location, true), uuid);
when(load.getWarpSigns()).thenReturn(warpMap);
when(handler.loadObject(anyString())).thenReturn(load);
@ -193,12 +204,14 @@ public class WarpSignsManagerTest {
when(addon.getSettings()).thenReturn(settings);
when(settings.getWelcomeLine()).thenReturn("[Welcome]");
when(settings.getLoreFormat()).thenReturn("&f");
when(settings.getIcon()).thenReturn("SIGN");
// Bukkit
PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
when(Bukkit.getPluginManager()).thenReturn(pim);
// Tags
when(Tag.STANDING_SIGNS.isTagged(Material.ACACIA_SIGN)).thenReturn(true);
// Players Manager
when(plugin.getPlayers()).thenReturn(pm);
when(pm.getName(uuid)).thenReturn("tastybento");
@ -210,6 +223,7 @@ public class WarpSignsManagerTest {
// IWM
when(plugin.getIWM()).thenReturn(iwm);
when(iwm.getPermissionPrefix(any())).thenReturn("bskyblock.");
when(iwm.getFriendlyName(any())).thenReturn("BSkyBlock");
// Island Manager
when(addon.getIslands()).thenReturn(im);
@ -217,7 +231,7 @@ public class WarpSignsManagerTest {
when(im.isSafeLocation(any())).thenReturn(true);
// WarpPanelManager
when(addon.getWarpPanelManager()).thenReturn(wpm);
when(addon.getSignCacheManager()).thenReturn(wpm);
wsm = new WarpSignsManager(addon, plugin);
}
@ -230,7 +244,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#getWarpMap(org.bukkit.World)}.
* Test method for {@link WarpSignsManager#getWarpMap(org.bukkit.World)}.
*/
@Test
public void testGetWarpMap() {
@ -238,7 +252,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#getWarpMap(org.bukkit.World)}.
* Test method for {@link WarpSignsManager#getWarpMap(org.bukkit.World)}.
*/
@Test
public void testGetWarpMapNullWorld() {
@ -248,7 +262,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#getWarpMap(org.bukkit.World)}.
* Test method for {@link WarpSignsManager#getWarpMap(org.bukkit.World)}.
*/
@Test
public void testGetWarpMapWrongBlockType() {
@ -258,18 +272,19 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#getWarpMap(org.bukkit.World)}.
* Test method for {@link WarpSignsManager#getWarpMap(org.bukkit.World)}.
*/
@Test
public void testGetWarpMapNullLocation() {
Map<Location, UUID> warpMap = Collections.singletonMap(null, uuid);
PlayerWarp playerWarp = new PlayerWarp(null, true);
Map<PlayerWarp, UUID> warpMap = Collections.singletonMap(playerWarp, uuid);
when(load.getWarpSigns()).thenReturn(warpMap);
wsm = new WarpSignsManager(addon, plugin);
assertTrue("Map is not empty", wsm.getWarpMap(world).isEmpty());
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#getWarpMap(org.bukkit.World)}.
* Test method for {@link WarpSignsManager#getWarpMap(org.bukkit.World)}.
* @throws Exception exception
*/
@Test
@ -280,7 +295,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#getWarpMap(org.bukkit.World)}.
* Test method for {@link WarpSignsManager#getWarpMap(org.bukkit.World)}.
*/
@Test
public void testGetWarpMapNothingInDatabase() {
@ -290,7 +305,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#WarpSignsManager(world.bentobox.warps.Warp, world.bentobox.bentobox.BentoBox)}.
* Test method for {@link WarpSignsManager#WarpSignsManager(world.bentobox.warps.Warp, world.bentobox.bentobox.BentoBox)}.
*/
@Test
public void testWarpSignsManager() {
@ -300,7 +315,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#addWarp(java.util.UUID, org.bukkit.Location)}.
* Test method for {@link WarpSignsManager#addWarp(java.util.UUID, org.bukkit.Location)}.
*/
@Test
public void testAddWarpNullPlayer() {
@ -308,7 +323,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#addWarp(java.util.UUID, org.bukkit.Location)}.
* Test method for {@link WarpSignsManager#addWarp(java.util.UUID, org.bukkit.Location)}.
*/
@Test
public void testAddWarpNullLocation() {
@ -316,7 +331,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#addWarp(java.util.UUID, org.bukkit.Location)}.
* Test method for {@link WarpSignsManager#addWarp(java.util.UUID, org.bukkit.Location)}.
*/
@Test
public void testAddWarpReplaceOldSign() {
@ -325,7 +340,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#addWarp(java.util.UUID, org.bukkit.Location)}.
* Test method for {@link WarpSignsManager#addWarp(java.util.UUID, org.bukkit.Location)}.
*/
@Test
public void testAddWarpReplaceOldSignDifferentPlayer() {
@ -334,33 +349,33 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#addWarp(java.util.UUID, org.bukkit.Location)}.
* Test method for {@link WarpSignsManager#addWarp(java.util.UUID, org.bukkit.Location)}.
*/
@Test
public void testAddWarp() {
Location loc = mock(Location.class);
assertTrue(wsm.addWarp(uuid, loc));
verify(pim).callEvent(any(WarpInitiateEvent.class));
verify(pim).callEvent(any(WarpCreateEvent.class));
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#getWarp(org.bukkit.World, java.util.UUID)}.
* Test method for {@link WarpSignsManager#getWarpLocation(org.bukkit.World, java.util.UUID)}.
*/
@Test
public void testGetWarpWorldWorld() {
assertNull(wsm.getWarp(mock(World.class), uuid));
assertNull(wsm.getWarpLocation(mock(World.class), uuid));
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#getWarp(org.bukkit.World, java.util.UUID)}.
* Test method for {@link WarpSignsManager#getWarpLocation(org.bukkit.World, java.util.UUID)}.
*/
@Test
public void testGetWarp() {
assertEquals(location, wsm.getWarp(world, uuid));
assertEquals(location, wsm.getWarpLocation(world, uuid));
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#getWarpOwner(org.bukkit.Location)}.
* Test method for {@link WarpSignsManager#getWarpOwner(org.bukkit.Location)}.
*/
@Test
public void testGetWarpOwner() {
@ -368,7 +383,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#getSortedWarps(org.bukkit.World)}.
* Test method for {@link WarpSignsManager#getSortedWarps(org.bukkit.World)}.
*/
@Test
public void testGetSortedWarps() {
@ -377,7 +392,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#listWarps(org.bukkit.World)}.
* Test method for {@link WarpSignsManager#listWarps(org.bukkit.World)}.
*/
@Test
public void testListWarps() {
@ -386,7 +401,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#removeWarp(org.bukkit.Location)}.
* Test method for {@link WarpSignsManager#removeWarp(org.bukkit.Location)}.
*/
@Test
public void testRemoveWarpLocation() {
@ -395,7 +410,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#removeWarp(org.bukkit.World, java.util.UUID)}.
* Test method for {@link WarpSignsManager#removeWarp(org.bukkit.World, java.util.UUID)}.
*/
@Test
public void testRemoveWarpWorldUUID() {
@ -404,7 +419,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#saveWarpList()}.
* Test method for {@link WarpSignsManager#saveWarpList()}.
* @throws Exception general exception
*/
@Test
@ -414,16 +429,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#getSignInfo(org.bukkit.World, java.util.UUID)}.
*/
@Test
public void testGetSignInfo() {
SignCacheItem sc = wsm.getSignInfo(world, uuid);
assertEquals(Material.ACACIA_SIGN, sc.getType());
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#warpPlayer(org.bukkit.World, world.bentobox.bentobox.api.user.User, java.util.UUID)}.
* Test method for {@link WarpSignsManager#warpPlayer(org.bukkit.World, world.bentobox.bentobox.api.user.User, java.util.UUID)}.
*/
@Test
public void testWarpPlayer() {
@ -432,16 +438,51 @@ public class WarpSignsManagerTest {
when(p.getWorld()).thenReturn(world);
when(p.getName()).thenReturn("tastybento");
when(p.getLocation()).thenReturn(location);
when(p.isOnline()).thenReturn(true);
when(p.canSee(any(Player.class))).thenReturn(true);
@Nullable
User u = User.getInstance(p);
PowerMockito.when(Util.teleportAsync(any(), any(), any())).thenReturn(CompletableFuture.completedFuture(true));
wsm.warpPlayer(world, u, uuid);
PowerMockito.verifyStatic(Util.class);
Util.teleportAsync(eq(p), any(), eq(TeleportCause.COMMAND));
verify(player).sendMessage("warps.player-warped");
verify(player).sendMessage(anyString());
verify(pim).callEvent(any(WarpInitiateEvent.class));
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#hasWarp(org.bukkit.World, java.util.UUID)}.
* Test method for {@link WarpSignsManager#warpPlayer(org.bukkit.World, world.bentobox.bentobox.api.user.User, java.util.UUID)}.
*/
@Test
public void testWarpPlayerEventCancelled() {
// Capture the event passed to callEvent
ArgumentCaptor<WarpInitiateEvent> eventCaptor = ArgumentCaptor.forClass(WarpInitiateEvent.class);
// Simulate the event being called and cancelled
doAnswer(invocation -> {
WarpInitiateEvent event = (WarpInitiateEvent) invocation.getArgument(0);
event.setCancelled(true);
return null;
}).when(pim).callEvent(eventCaptor.capture());
Player p = mock(Player.class);
when(p.getUniqueId()).thenReturn(UUID.randomUUID());
when(p.getWorld()).thenReturn(world);
when(p.getName()).thenReturn("tastybento");
when(p.getLocation()).thenReturn(location);
when(p.isOnline()).thenReturn(true);
when(p.canSee(any(Player.class))).thenReturn(true);
@Nullable
User u = User.getInstance(p);
PowerMockito.when(Util.teleportAsync(any(), any(), any())).thenReturn(CompletableFuture.completedFuture(true));
wsm.warpPlayer(world, u, uuid);
PowerMockito.verifyStatic(Util.class, never());
Util.teleportAsync(eq(p), any(), eq(TeleportCause.COMMAND));
verify(player, never()).sendMessage(anyString());
}
/**
* Test method for {@link WarpSignsManager#hasWarp(org.bukkit.World, java.util.UUID)}.
*/
@Test
public void testHasWarp() {
@ -451,7 +492,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#loadWarpList()}.
* Test method for {@link WarpSignsManager#loadWarpList()}.
*/
@Test
public void testLoadWarpListNoWarpTable() {
@ -466,7 +507,7 @@ public class WarpSignsManagerTest {
}
/**
* Test method for {@link world.bentobox.warps.WarpSignsManager#loadWarpList()}.
* Test method for {@link WarpSignsManager#loadWarpList()}.
* @throws Exception exception
*/
@Test

View File

@ -38,7 +38,7 @@ import world.bentobox.bentobox.managers.CommandsManager;
import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.managers.PlayersManager;
import world.bentobox.warps.Warp;
import world.bentobox.warps.WarpSignsManager;
import world.bentobox.warps.managers.WarpSignsManager;
import world.bentobox.warps.config.Settings;
/**

View File

@ -7,10 +7,8 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import org.bukkit.Bukkit;
import org.bukkit.World;
@ -29,9 +27,9 @@ import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.managers.CommandsManager;
import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.managers.PlayersManager;
import world.bentobox.warps.managers.SignCacheManager;
import world.bentobox.warps.Warp;
import world.bentobox.warps.WarpPanelManager;
import world.bentobox.warps.WarpSignsManager;
import world.bentobox.warps.managers.WarpSignsManager;
import world.bentobox.warps.config.Settings;
/**
@ -62,7 +60,7 @@ public class WarpsCommandTest {
@Mock
private PlayersManager pm;
@Mock
private WarpPanelManager wpm;
private SignCacheManager wpm;
/**
*/
@ -99,8 +97,13 @@ public class WarpsCommandTest {
set.add(UUID.randomUUID());
when(wsm.listWarps(world)).thenReturn(set);
CompletableFuture<List<UUID>> warps = new CompletableFuture<>();
warps.complete(set.stream().toList());
when(wsm.getSortedWarps(world)).thenReturn(warps);
// Warp Panel Manager
when(addon.getWarpPanelManager()).thenReturn(wpm);
when(addon.getSignCacheManager()).thenReturn(wpm);
}
@ -120,7 +123,7 @@ public class WarpsCommandTest {
@Test
public void testSetupWarpCompositeCommand() {
warpCommandWarpsCompositeCommand();
assertEquals("bskyblock.island.warp", wc.getPermission());
assertEquals("bskyblock.island.warps", wc.getPermission());
assertTrue(wc.isOnlyPlayer());
assertEquals("warps.help.description", wc.getDescription());
}
@ -131,7 +134,7 @@ public class WarpsCommandTest {
@Test
public void testSetupWarp() {
warpCommandWarps();
assertEquals(Warp.WELCOME_WARP_SIGNS + ".warp", wc.getPermission());
assertEquals(Warp.WELCOME_WARP_SIGNS + ".warps", wc.getPermission());
assertTrue(wc.isOnlyPlayer());
assertEquals("warps.help.description", wc.getDescription());
}
@ -168,7 +171,6 @@ public class WarpsCommandTest {
public void testExecuteUserStringListOfString() {
warpCommandWarpsCompositeCommand();
assertTrue(wc.execute(user, "warps", Collections.emptyList()));
verify(wpm).showWarpPanel(world, user, 0);
}
/**
@ -178,7 +180,6 @@ public class WarpsCommandTest {
public void testExecuteUserStringListOfStringNoAddon() {
warpCommandWarps();
assertTrue(wc.execute(user, "warps", Collections.emptyList()));
verify(wpm).showWarpPanel(world, user, 0);
}
}

View File

@ -8,10 +8,7 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.*;
import java.util.HashMap;
import java.util.Map;
@ -44,14 +41,18 @@ import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.events.flags.FlagProtectionChangeEvent;
import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.managers.LocalesManager;
import world.bentobox.bentobox.managers.PlaceholdersManager;
import world.bentobox.bentobox.util.Util;
import world.bentobox.warps.objects.PlayerWarp;
import world.bentobox.warps.Warp;
import world.bentobox.warps.WarpSignsManager;
import world.bentobox.warps.managers.WarpSignsManager;
import world.bentobox.warps.config.Settings;
/**
@ -83,6 +84,8 @@ public class WarpSignsListenerTest {
private IslandsManager im;
@Mock
private IslandWorldManager iwm;
@Mock
private Island island;
@Before
public void setUp() {
@ -121,16 +124,16 @@ public class WarpSignsListenerTest {
when(block.getState()).thenReturn(s);
// warp signs manager
when(addon.getWarpSignsManager()).thenReturn(wsm);
Map<UUID, Location> list = new HashMap<>();
Map<UUID, PlayerWarp> list = new HashMap<>();
Location location = mock(Location.class);
when(location.getBlock()).thenReturn(block);
when(s.getLocation()).thenReturn(location);
when(block.getLocation()).thenReturn(location);
list.put(uuid, location);
list.put(uuid, new PlayerWarp(location, true));
// Player is in world
when(wsm.getWarpMap(world)).thenReturn(list);
//Player has a warp sign already here
when(wsm.getWarp(any(), any())).thenReturn(location);
when(wsm.getWarpLocation(any(), any())).thenReturn(location);
// Unique spot
when(wsm.addWarp(any(), any())).thenReturn(true);
// Bentobox
@ -148,6 +151,9 @@ public class WarpSignsListenerTest {
when(settings.getWelcomeLine()).thenReturn("[WELCOME]");
when(addon.getSettings()).thenReturn(settings);
island = mock(Island.class);
when(im.getIslandAt(any())).thenReturn(Optional.of(island));
// On island
when(plugin.getIslands()).thenReturn(im);
when(im.userIsOnIsland(any(World.class), any(User.class))).thenReturn(true);
@ -299,6 +305,54 @@ public class WarpSignsListenerTest {
assertEquals(ChatColor.GREEN + "[WELCOME]", e.getLine(0));
}
@Test
public void testOnCreateWithoutCorrectRankNotAllowed() {
WarpSignsListener wsl = new WarpSignsListener(addon);
SignChangeEvent e = new SignChangeEvent(block, player, lines);
when(player.hasPermission(anyString())).thenReturn(true);
when(addon.inRegisteredWorld(any())).thenReturn(true);
when(island.getRank(player.getUniqueId())).thenReturn(0);
when(island.getFlag(any())).thenReturn(1000);
wsl.onSignWarpCreate(e);
verify(player).sendMessage("warps.error.not-correct-rank");
}
@Test
public void testOnFlagChangeWhenSettingIsOffNothingHappens() {
Flag flag = mock(Flag.class);
when(addon.getCreateWarpFlag()).thenReturn(flag);
when(settings.getRemoveExistingWarpsWhenFlagChanges()).thenReturn(false);
WarpSignsListener wsl = new WarpSignsListener(addon);
FlagProtectionChangeEvent e = new FlagProtectionChangeEvent(island, player.getUniqueId(), flag, 1000);
wsl.onFlagChange(e);
verifyNoInteractions(island);
}
@Test
public void testOnFlagChangeWhenSettingIsOnWarpGetsRemoved() {
Flag flag = mock(Flag.class);
when(addon.getCreateWarpFlag()).thenReturn(flag);
when(settings.getRemoveExistingWarpsWhenFlagChanges()).thenReturn(true);
WarpSignsListener wsl = new WarpSignsListener(addon);
Map<UUID, PlayerWarp> warps = Map.of(
player.getUniqueId(), new PlayerWarp(block.getLocation(), true)
);
when(wsm.getWarpMap(any())).thenReturn(warps);
when(island.inIslandSpace(any(Location.class))).thenReturn(true);
FlagProtectionChangeEvent e = new FlagProtectionChangeEvent(island, player.getUniqueId(), flag, 1000);
wsl.onFlagChange(e);
verify(addon.getWarpSignsManager()).removeWarp(any(), any());
}
@Test
public void testOnCreateNotGameWorldNotAllowed() {
when(settings.isAllowInOtherWorlds()).thenReturn(false);
@ -367,7 +421,7 @@ public class WarpSignsListenerTest {
@Test
public void testCreateNoSignAlreadyUniqueSpot() {
when(wsm.getWarp(any(), any())).thenReturn(null);
when(wsm.getWarpLocation(any(), any())).thenReturn(null);
when(player.hasPermission(anyString())).thenReturn(true);
WarpSignsListener wsl = new WarpSignsListener(addon);
SignChangeEvent e = new SignChangeEvent(block, player, lines);