Merge branch 'develop' into 2_0_0_multi_island

This commit is contained in:
tastybento 2023-09-03 09:04:38 -07:00
commit 9b56b39647
13 changed files with 4164 additions and 1144 deletions

View File

@ -252,6 +252,8 @@ public class BentoBox extends JavaPlugin implements Listener {
// Tell all addons that everything is loaded
isLoaded = true;
this.addonsManager.allLoaded();
// Run ready commands
settings.getReadyCommands().forEach(cmd -> Bukkit.getServer().dispatchCommand(getServer().getConsoleSender(), cmd));
// Fire plugin ready event - this should go last after everything else
Bukkit.getPluginManager().callEvent(new BentoBoxReadyEvent());
instance.log("All blueprints loaded.");

View File

@ -1,12 +1,18 @@
package world.bentobox.bentobox;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.bukkit.Material;
import com.google.common.collect.ImmutableList;
import world.bentobox.bentobox.api.configuration.ConfigComment;
import world.bentobox.bentobox.api.configuration.ConfigEntry;
import world.bentobox.bentobox.api.configuration.ConfigObject;
@ -22,26 +28,6 @@ import world.bentobox.bentobox.database.DatabaseSetup.DatabaseType;
@StoreAt(filename="config.yml") // Explicitly call out what name this should have.
@ConfigComment("BentoBox v[version] configuration file.")
@ConfigComment("")
@ConfigComment("This configuration file contains settings that mainly apply to or manage the following elements:")
@ConfigComment(" * Data storage")
@ConfigComment(" * Gamemodes (commands, ...)")
@ConfigComment(" * Internet connectivity (web-based content-enriched features, ...)")
@ConfigComment("")
@ConfigComment("Note that this configuration file is dynamic:")
@ConfigComment(" * It gets updated with the newest settings and comments after BentoBox loaded its settings from it.")
@ConfigComment(" * Upon updating BentoBox, new settings will be automatically added into this configuration file.")
@ConfigComment(" * Said settings are distinguishable by a dedicated comment, which looks like this:")
@ConfigComment(" Added since X.Y.Z.")
@ConfigComment(" * They are provided with default values that should not cause issues on live production servers.")
@ConfigComment(" * You can however edit this file while the server is online.")
@ConfigComment(" You will therefore need to run the following command in order to take the changes into account: /bentobox reload.")
@ConfigComment("")
@ConfigComment("Here are a few pieces of advice before you get started:")
@ConfigComment(" * You should check out our Wiki, which may provide you useful tips or insights about BentoBox's features.")
@ConfigComment(" Link: https://github.com/BentoBoxWorld/BentoBox/wiki")
@ConfigComment(" * You should edit this configuration file while the server is offline.")
@ConfigComment(" * Moreover, whenever you update BentoBox, you should do so on a test server first.")
@ConfigComment(" This will allow you to configure the new settings beforehand instead of applying them inadvertently on a live production server.")
public class Settings implements ConfigObject {
/* GENERAL */
@ -56,10 +42,17 @@ public class Settings implements ConfigObject {
@ConfigEntry(path = "general.use-economy")
private boolean useEconomy = true;
/* COMMANDS */
@ConfigComment("Console commands to run when BentoBox has loaded all worlds and addons.")
@ConfigComment("Commands are run as the console.")
@ConfigComment("e.g. set aliases for worlds in Multiverse here, or anything you need to")
@ConfigComment("run after the plugin is fully loaded.")
@ConfigEntry(path = "general.ready-commands", since = "1.24.2")
private List<String> readyCommands = new ArrayList<>();
// Database
@ConfigComment("JSON, MYSQL, MARIADB, MONGODB, SQLITE, POSTGRESQL and YAML(deprecated).")
@ConfigComment("JSON, MYSQL, MARIADB, MONGODB, SQLITE, and POSTGRESQL.")
@ConfigComment("Transition database options are:")
@ConfigComment(" YAML2JSON, YAML2MARIADB, YAML2MYSQL, YAML2MONGODB, YAML2SQLITE")
@ConfigComment(" JSON2MARIADB, JSON2MYSQL, JSON2MONGODB, JSON2SQLITE, JSON2POSTGRESQL")
@ConfigComment(" MYSQL2JSON, MARIADB2JSON, MONGODB2JSON, SQLITE2JSON, POSTGRESQL2JSON")
@ConfigComment("If you need others, please make a feature request.")
@ -70,7 +63,7 @@ public class Settings implements ConfigObject {
@ConfigComment(" SQLite versions 3.28 or later")
@ConfigComment(" PostgreSQL versions 9.4 or later")
@ConfigComment("Transition options enable migration from one database type to another. Use /bbox migrate.")
@ConfigComment("YAML and JSON are file-based databases.")
@ConfigComment("JSON is a file-based database.")
@ConfigComment("MYSQL might not work with all implementations: if available, use a dedicated database type (e.g. MARIADB).")
@ConfigComment("BentoBox uses HikariCP for connecting with SQL databases.")
@ConfigComment("If you use MONGODB, you must also run the BSBMongo plugin (not addon).")
@ -1045,6 +1038,20 @@ public class Settings implements ConfigObject {
this.safeSpotSearchRange = safeSpotSearchRange;
}
/**
* @return an immutable list of readyCommands
*/
public List<String> getReadyCommands() {
return ImmutableList.copyOf(Objects.requireNonNullElse(readyCommands, Collections.emptyList()));
}
/**
* @param readyCommands the readyCommands to set
*/
public void setReadyCommands(List<String> readyCommands) {
this.readyCommands = readyCommands;
}
/**
* @return the islandNumber
* @since 2.0.0
@ -1060,4 +1067,5 @@ public class Settings implements ConfigObject {
public void setIslandNumber(int islandNumber) {
this.islandNumber = islandNumber;
}
}

View File

@ -64,19 +64,18 @@ public class TemplatedPanel extends Panel
*/
private void generatePanel()
{
Map<Integer, PanelItem> items = switch (this.panelTemplate.type())
{
case INVENTORY -> this.populateInventoryPanel();
case HOPPER -> this.populateHopperPanel();
case DROPPER -> this.populateDropperPanel();
};
Map<Integer, PanelItem> items = switch (this.panelTemplate.type()) {
case INVENTORY -> this.populateInventoryPanel(new PanelItem[6][9]);
case HOPPER -> this.populateInventoryPanel(new PanelItem[1][5]);
case DROPPER -> this.populateInventoryPanel(new PanelItem[3][3]);
};
super.makePanel(this.user.getTranslation(this.panelTemplate.title(), this.parameters),
items,
items.keySet().stream().max(Comparator.naturalOrder()).orElse(9),
this.user,
this.getListener().orElse(null),
this.panelTemplate.type());
super.makePanel(this.user.getTranslation(this.panelTemplate.title(), this.parameters),
items,
items.keySet().stream().max(Comparator.naturalOrder()).orElse(9),
this.user,
this.getListener().orElse(null),
this.panelTemplate.type());
}
/**
@ -85,176 +84,33 @@ public class TemplatedPanel extends Panel
* @return Map that contains indexes linked to the correct panel item.
*/
@NonNull
private Map<Integer, PanelItem> populateInventoryPanel() {
PanelItem[][] itemArray = new PanelItem[6][9];
processItemData(itemArray);
removeEmptyLines(itemArray);
fillBorder(itemArray);
fillBackground(itemArray);
return createItemMap(itemArray);
private Map<Integer, PanelItem> populateInventoryPanel(PanelItem[][] itemArray)
{
this.preProcessPanelTemplate(itemArray);
this.processItemData(itemArray);
this.removeEmptyLines(itemArray);
this.fillBorder(itemArray);
this.fillBackground(itemArray);
return this.createItemMap(itemArray);
}
private void processItemData(PanelItem[][] itemArray) {
/**
* This method processes what items should be added into the panel.
* It counts how many same type buttons should be generated.
* This cannot be done in the same step as creating button.
* @param itemArray The double array with items into panel
*/
private void preProcessPanelTemplate(PanelItem[][] itemArray)
{
final int numRows = itemArray.length;
final int numCols = itemArray[0].length;
// Analyze the GUI button layout a bit.
for (int i = 0; i < panelTemplate.content().length; i++) {
for (int k = 0; k < panelTemplate.content()[i].length; k++) {
ItemTemplateRecord rec = panelTemplate.content()[i][k];
if (rec != null && rec.dataMap().containsKey("type")) {
String type = String.valueOf(rec.dataMap().get("type"));
int counter = typeSlotMap.computeIfAbsent(type, key -> 0);
typeSlotMap.put(type, counter + 1);
}
// Make buttons for the GUI
itemArray[i][k] = makeButton(panelTemplate.content()[i][k]);
}
}
}
private void removeEmptyLines(PanelItem[][] itemArray) {
boolean[] showLine = panelTemplate.forcedRows();
for (int i = 0; i < panelTemplate.content().length; i++) {
boolean emptyLine = true;
for (int k = 0; emptyLine && k < panelTemplate.content()[i].length; k++) {
emptyLine = itemArray[i][k] == null;
}
showLine[i] = showLine[i] || !emptyLine;
}
}
private void fillBorder(PanelItem[][] itemArray) {
if (panelTemplate.border() == null) {
return;
}
PanelItem template = makeTemplate(panelTemplate.border());
int numRows = itemArray.length;
int numCols = itemArray[0].length;
for (int i = 0; i < numRows; i++) {
if (i == 0 || i == numRows - 1) {
// Fill first and last row completely with border.
for (int k = 0; k < numCols; k++) {
if (itemArray[i][k] == null) {
itemArray[i][k] = template;
}
}
} else {
// Fill first and last element in row with border.
if (itemArray[i][0] == null) {
itemArray[i][0] = template;
}
if (itemArray[i][numCols - 1] == null) {
itemArray[i][numCols - 1] = template;
}
}
}
panelTemplate.forcedRows()[0] = true;
panelTemplate.forcedRows()[numRows - 1] = true;
}
private void fillBackground(PanelItem[][] itemArray) {
if (panelTemplate.background() != null) {
PanelItem template = makeTemplate(panelTemplate.background());
for (int i = 0; i < 6; i++) {
for (int k = 0; k < 9; k++) {
if (itemArray[i][k] == null) {
itemArray[i][k] = template;
}
}
}
}
}
private Map<Integer, PanelItem> createItemMap(PanelItem[][] itemArray) {
Map<Integer, PanelItem> itemMap = new HashMap<>(6 * 9);
int correctIndex = 0;
for (int i = 0; i < itemArray.length; i++) {
final boolean iterate = panelTemplate.forcedRows()[i];
for (int k = 0; iterate && k < itemArray[i].length; k++) {
if (itemArray[i][k] != null) {
itemMap.put(correctIndex, itemArray[i][k]);
}
correctIndex++;
}
}
return itemMap;
}
/**
* This method creates map with item indexes and their icons that will be added into
* hopper Panel.
* @return Map that contains indexes linked to the correct panel item.
*/
@NonNull
private Map<Integer, PanelItem> populateHopperPanel()
{
// Init item array with the max available size.
PanelItem[] itemArray = new PanelItem[5];
// Analyze the template
for (int i = 0; i < 5; i++)
for (int i = 0; i < numRows; i++)
{
ItemTemplateRecord rec = this.panelTemplate.content()[0][i];
if (rec != null && rec.dataMap().containsKey("type"))
{
String type = String.valueOf(rec.dataMap().get("type"));
int counter = this.typeSlotMap.computeIfAbsent(type, key -> 0);
this.typeSlotMap.put(type, counter + 1);
}
}
// Make buttons
for (int i = 0; i < 5; i++)
{
itemArray[i] = this.makeButton(this.panelTemplate.content()[0][i]);
}
// Now fill the background.
if (this.panelTemplate.background() != null)
{
PanelItem template = this.makeTemplate(this.panelTemplate.background());
for (int i = 0; i < 5; i++)
{
if (itemArray[i] == null)
{
itemArray[i] = template;
}
}
}
// Now place all panel items with their indexes into item map.
Map<Integer, PanelItem> itemMap = new HashMap<>(5);
int correctIndex = 0;
for (PanelItem panelItem : itemArray)
{
if (panelItem != null)
{
itemMap.put(correctIndex, panelItem);
}
correctIndex++;
}
return itemMap;
}
/**
* This method creates map with item indexes and their icons that will be added into
* dropper Panel.
* @return Map that contains indexes linked to the correct panel item.
*/
@NonNull
private Map<Integer, PanelItem> populateDropperPanel()
{
// Analyze the template
for (int i = 0; i < 3; i++)
{
for (int k = 0; k < 3; k++)
for (int k = 0; k < numCols; k++)
{
ItemTemplateRecord rec = this.panelTemplate.content()[i][k];
@ -267,27 +123,78 @@ public class TemplatedPanel extends Panel
}
}
}
}
// Init item array with the max available size.
PanelItem[][] itemArray = new PanelItem[3][3];
// Make buttons
for (int i = 0; i < 3; i++)
/**
* This method populates item array with all buttons.
* @param itemArray The double array with items into panel
*/
private void processItemData(PanelItem[][] itemArray)
{
final int numRows = itemArray.length;
final int numCols = itemArray[0].length;
for (int i = 0; i < numRows; i++)
{
for (int k = 0; k < 3; k++)
for (int k = 0; k < numCols; k++)
{
itemArray[i][k] = this.makeButton(this.panelTemplate.content()[i][k]);
}
}
}
// Now fill the background.
if (this.panelTemplate.background() != null)
/**
* This method removes all empty lines if they are not forced to be
* showed.
* @param itemArray The double array with items into panel
*/
private void removeEmptyLines(PanelItem[][] itemArray)
{
// After items are created, remove empty lines.
boolean[] showLine = this.panelTemplate.forcedRows();
final int numRows = itemArray.length;
final int numCols = itemArray[0].length;
for (int i = 0; i < numRows; i++)
{
PanelItem template = this.makeTemplate(this.panelTemplate.background());
boolean emptyLine = true;
for (int i = 0; i < 3; i++)
for (int k = 0; emptyLine && k < numCols; k++)
{
for (int k = 0; k < 3; k++)
emptyLine = itemArray[i][k] == null;
}
// Do not generate fallback for "empty" lines.
showLine[i] = showLine[i] || !emptyLine;
}
}
/**
* This method fills border elements with item from template.
* @param itemArray The double array with items into panel
*/
private void fillBorder(PanelItem[][] itemArray)
{
if (this.panelTemplate.border() == null)
{
// Ugly return because tasty does not like extra {}.
return;
}
PanelItem template = makeTemplate(this.panelTemplate.border());
final int numRows = itemArray.length;
final int numCols = itemArray[0].length;
for (int i = 0; i < numRows; i++)
{
if (i == 0 || i == numRows - 1)
{
// Fill first and last row completely with border.
for (int k = 0; k < numCols; k++)
{
if (itemArray[i][k] == null)
{
@ -295,16 +202,69 @@ public class TemplatedPanel extends Panel
}
}
}
else
{
// Fill first and last element in row with border.
if (itemArray[i][0] == null)
{
itemArray[i][0] = template;
}
if (itemArray[i][numCols - 1] == null)
{
itemArray[i][numCols - 1] = template;
}
}
}
// Init item map with the max available size.
Map<Integer, PanelItem> itemMap = new HashMap<>(9);
this.panelTemplate.forcedRows()[0] = true;
this.panelTemplate.forcedRows()[numRows - 1] = true;
}
/**
* This method fills background elements with item from template.
* @param itemArray The double array with items into panel
*/
private void fillBackground(PanelItem[][] itemArray)
{
if (this.panelTemplate.background() == null)
{
return;
}
PanelItem template = this.makeTemplate(this.panelTemplate.background());
final int numRows = itemArray.length;
final int numCols = itemArray[0].length;
for (int i = 0; i < numRows; i++)
{
for (int k = 0; k < numCols; k++)
{
if (itemArray[i][k] == null)
{
itemArray[i][k] = template;
}
}
}
}
/**
* This method converts to PanelItem array to the correct item map.
* @param itemArray The double array with items into panel
* @return The map that links index of button to panel item.
*/
private Map<Integer, PanelItem> createItemMap(PanelItem[][] itemArray)
{
Map<Integer, PanelItem> itemMap = new HashMap<>(itemArray.length * itemArray[0].length);
int correctIndex = 0;
for (int i = 0; i < 3; i++)
for (int i = 0; i < itemArray.length; i++)
{
for (int k = 0; k < 3; k++)
final boolean iterate = this.panelTemplate.forcedRows()[i];
for (int k = 0; iterate && k < itemArray[i].length; k++)
{
if (itemArray[i][k] != null)
{
@ -361,8 +321,8 @@ public class TemplatedPanel extends Panel
// If there are generic click handlers that could be added, then this is a place
// where to process them.
// Click Handlers are managed by custom addon buttons.
return itemBuilder.build();
// Click Handlers are managed by custom addon buttons.
return itemBuilder.build();
}
}
@ -388,8 +348,8 @@ public class TemplatedPanel extends Panel
// Get next slot index.
ItemSlot itemSlot = this.typeIndex.containsKey(type) ?
this.typeIndex.get(type) :
new ItemSlot(0, this.typeSlotMap);
this.typeIndex.get(type) :
new ItemSlot(0, this);
this.typeIndex.put(type, itemSlot.nextItemSlot());
// Try to get next object.
@ -442,9 +402,9 @@ public class TemplatedPanel extends Panel
}
// ---------------------------------------------------------------------
// Section: Classes
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Section: Classes
// ---------------------------------------------------------------------
/**
@ -452,9 +412,9 @@ public class TemplatedPanel extends Panel
* panel with it.
* Some buttons need information about all types, like previous/next.
* @param slot Index of object in current panel.
* @param amountMap Map that links types with number of objects in panel.
* @param parentPanel The parent panel for current Item.
*/
public record ItemSlot(int slot, Map<String, Integer> amountMap)
public record ItemSlot(int slot, TemplatedPanel parentPanel)
{
/**
* This method returns new record object with iterative slot index.
@ -462,14 +422,38 @@ public class TemplatedPanel extends Panel
*/
ItemSlot nextItemSlot()
{
return new ItemSlot(this.slot() + 1, this.amountMap());
return new ItemSlot(this.slot() + 1, this.parentPanel());
}
/**
* This method returns map that links button types with a number of slots that this button
* is present.
* @return Map that links button type to amount in the gui.
* @deprecated Use {@link #amount(String)} instead.
*/
@Deprecated
public Map<String, Integer> amountMap()
{
return this.parentPanel.typeSlotMap;
}
/**
* This returns amount of slots for given button type.
* @param type Type of the button.
* @return Number of slots in panel.
*/
public int amount(String type)
{
return this.parentPanel.typeSlotMap.getOrDefault(type, 0);
}
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**

View File

@ -167,11 +167,11 @@ public class BlueprintClipboard {
* @param b - bounding box
* @return - list of vectors
*/
private List<Vector> getVectors(BoundingBox b) {
protected List<Vector> getVectors(BoundingBox b) {
List<Vector> r = new ArrayList<>();
for (int y = (int)b.getMinY(); y <= b.getMaxY(); y++) {
for (int x = (int)b.getMinX(); x <= b.getMaxX(); x++) {
for (int z = (int)b.getMinZ(); z <= b.getMaxZ(); z++) {
for (int y = (int) Math.floor(b.getMinY()); y <= b.getMaxY(); y++) {
for (int x = (int) Math.floor(b.getMinX()); x <= b.getMaxX(); x++) {
for (int z = (int) Math.floor(b.getMinZ()); z <= b.getMaxZ(); z++) {
r.add(new Vector(x,y,z));
}
}

View File

@ -610,6 +610,9 @@ public class Island implements DataObject, MetaDataAble {
* @return rank integer
*/
public int getRank(User user) {
if (user.isOp()) {
return RanksManager.ADMIN_RANK;
}
return members.getOrDefault(user.getUniqueId(), RanksManager.VISITOR_RANK);
}

View File

@ -4,7 +4,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.World;
@ -16,12 +15,14 @@ import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.panels.Panel;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.PanelItem.ClickHandler;
import world.bentobox.bentobox.api.panels.TabbedPanel;
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.lists.Flags;
import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.bentobox.panels.settings.SettingsTab;
import world.bentobox.bentobox.util.Util;
/**
@ -31,12 +32,19 @@ import world.bentobox.bentobox.util.Util;
public class CommandRankClickListener implements ClickHandler {
private final BentoBox plugin = BentoBox.getInstance();
private Island island;
/* (non-Javadoc)
* @see world.bentobox.bentobox.api.panels.PanelItem.ClickHandler#onClick(world.bentobox.bentobox.api.panels.Panel, world.bentobox.bentobox.api.user.User, org.bukkit.event.inventory.ClickType, int)
*/
@Override
public boolean onClick(Panel panel, User user, ClickType clickType, int slot) {
// This click listener is used with TabbedPanel and SettingsTabs only
TabbedPanel tp = (TabbedPanel)panel;
SettingsTab st = (SettingsTab)tp.getActiveTab();
// Get the island for this tab
island = st.getIsland();
// Get the world
if (!user.inWorld()) {
user.sendMessage("general.errors.wrong-world");
@ -55,17 +63,16 @@ public class CommandRankClickListener implements ClickHandler {
return true;
}
// Get the user's island
Island island = plugin.getIslands().getIsland(panel.getWorld().orElse(user.getWorld()), user.getUniqueId());
if (island == null || island.getOwner() == null || !island.isAllowed(user, Flags.CHANGE_SETTINGS)) {
user.sendMessage("general.errors.insufficient-rank",
TextVariables.RANK,
user.getTranslation(plugin.getRanksManager().getRank(Objects.requireNonNull(island).getRank(user))));
// Check if user has rank enough on the island
//Island island = plugin.getIslands().getIsland(panel.getWorld().orElse(user.getWorld()), user.getUniqueId());
if (!island.isAllowed(user, Flags.CHANGE_SETTINGS)) {
String rank = user.getTranslation(plugin.getRanksManager().getRank(Objects.requireNonNull(island).getRank(user)));
user.sendMessage("general.errors.insufficient-rank", TextVariables.RANK, rank);
user.getPlayer().playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F);
return true;
}
String panelName = user.getTranslation("protection.flags.COMMAND_RANKS.name");
if (panel.getName().equals(panelName)) {
// This is a click on the panel
@ -100,7 +107,6 @@ public class CommandRankClickListener implements ClickHandler {
* @return panel item for this command
*/
public PanelItem getPanelItem(String c, User user, World world) {
Island island = plugin.getIslands().getIsland(world, user);
PanelItemBuilder pib = new PanelItemBuilder();
pib.name(c);
pib.clickHandler(new CommandCycleClick(this, c));
@ -126,7 +132,7 @@ public class CommandRankClickListener implements ClickHandler {
.filter(c -> c.getWorld() != null && c.getWorld().equals(world))
.forEach(c -> result.addAll(getCmdRecursively("/", c)));
if (result.size() > 49) {
Bukkit.getLogger().severe("Number of rank setting commands is too big for GUI");
plugin.logError("Number of rank setting commands is too big for GUI");
result.subList(49, result.size()).clear();
}
return result;

View File

@ -1,25 +1,5 @@
# BentoBox {$version} configuration file.
#
# This configuration file contains settings that mainly apply to or manage the following elements:
# * Data storage
# * Gamemodes (commands, ...)
# * Internet connectivity (web-based content-enriched features, ...)
#
# Note that this configuration file is dynamic:
# * It gets updated with the newest settings and comments after BentoBox loaded its settings from it.
# * Upon updating BentoBox, new settings will be automatically added into this configuration file.
# * Said settings are distinguishable by a dedicated comment, which looks like this:
# Added since X.Y.Z.
# * They are provided with default values that should not cause issues on live production servers.
# * You can however edit this file while the server is online.
# You will therefore need to run the following command in order to take the changes into account: /bentobox reload.
#
# Here are a few pieces of advice before you get started:
# * You should check out our Wiki, which may provide you useful tips or insights about BentoBox's features.
# Link: https://github.com/BentoBoxWorld/BentoBox/wiki
# * You should edit this configuration file while the server is offline.
# * Moreover, whenever you update BentoBox, you should do so on a test server first.
# This will allow you to configure the new settings beforehand instead of applying them inadvertently on a live production server.
general:
# Default language for new players.
# This is the filename in the locale folder without .yml.
@ -28,10 +8,15 @@ general:
# Use economy or not. If true, an economy plugin is required. If false, no money is used or given.
# If there is no economy plugin present anyway, money will be automatically disabled.
use-economy: true
# Console commands to run when BentoBox has loaded all worlds and addons.
# Commands are run as the console.
# e.g. set aliases for worlds in Multiverse here, or anything you need to
# run after the plugin is fully loaded.
# Added since 1.24.2.
ready-commands: []
database:
# JSON, MYSQL, MARIADB, MONGODB, SQLITE, POSTGRESQL and YAML(deprecated).
# JSON, MYSQL, MARIADB, MONGODB, SQLITE, and POSTGRESQL.
# Transition database options are:
# YAML2JSON, YAML2MARIADB, YAML2MYSQL, YAML2MONGODB, YAML2SQLITE
# JSON2MARIADB, JSON2MYSQL, JSON2MONGODB, JSON2SQLITE, JSON2POSTGRESQL
# MYSQL2JSON, MARIADB2JSON, MONGODB2JSON, SQLITE2JSON, POSTGRESQL2JSON
# If you need others, please make a feature request.
@ -42,7 +27,7 @@ general:
# SQLite versions 3.28 or later
# PostgreSQL versions 9.4 or later
# Transition options enable migration from one database type to another. Use /bbox migrate.
# YAML and JSON are file-based databases.
# JSON is a file-based database.
# MYSQL might not work with all implementations: if available, use a dedicated database type (e.g. MARIADB).
# BentoBox uses HikariCP for connecting with SQL databases.
# If you use MONGODB, you must also run the BSBMongo plugin (not addon).
@ -59,11 +44,11 @@ general:
# This helps prevent issues if the server crashes.
# Data is also saved at important points in the game.
backup-period: 5
# How many players will be saved in one tick. Default is 20
# How many players will be saved in one tick. Default is 200
# Reduce if you experience lag while saving.
# Do not set this too low or data might get lost!
max-saved-players-per-tick: 20
# How many islands will be saved in one tick. Default is 20
# How many islands will be saved in one tick. Default is 200
# Reduce if you experience lag while saving.
# Do not set this too low or data might get lost!
max-saved-islands-per-tick: 20
@ -82,8 +67,8 @@ general:
prefix-character: ''
# Custom connection datasource properties that will be applied to connection pool.
# Check available values to your SQL driver implementation.
# Example: ")
# custom-properties:
# Example:
# custom-properties:
# cachePrepStmts: 'true'
# prepStmtCacheSize: '250'
# prepStmtCacheSqlLimit: '2048'

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,20 @@
---
meta:
banner: WHITE_BANNER:1:CIRCLE_MIDDLE:RED
authors:
- mozzaf1ato
- tastybento
banner: WHITE_BANNER:1:CIRCLE_MIDDLE:RED
prefixes:
bentobox: "&6 BentoBox &7 &l > &r "
general:
success: "&a成否"
invalid: 無効
errors:
command-cancelled: "&cCommandはキャンセルされました。"
no-permission: "&cこのコマンドを実行する権限がありません ([permission])。"
use-in-game: "&cこのコマンドは、ゲームでのみ利用可能です。"
insufficient-rank: "&c ランクは十分に高くありません! (&7 [rank]&c )"
use-in-game: "&c このコマンドはゲーム内でのみ使用できます。"
use-in-console: "&c このコマンドはコンソールでのみ使用できます。"
no-team: "&cあなたはチームを持っていない!"
no-island: "&cあなたは島を持っていない!"
player-has-island: "&cこのプレイヤーはすでに島を持っている!"
@ -18,6 +22,7 @@ general:
already-have-island: "&cあなたはすでに島を持っている!"
no-safe-location-found: "&c島にテレポートする安全な場所が見つかりませんでした。"
not-owner: "&cあなたは島の所有者ではありません"
player-is-not-owner: "&b [name] &c は島の所有者ではありません!"
not-in-team: "&cそのプレイヤーはあなたのチームにはいない!"
offline-player: "&cそのプレイヤーはオフラインまたは存在しません。"
unknown-player: "&c[name]というプレイヤーは存在しません!"
@ -26,14 +31,13 @@ general:
wrong-world: "&cあなたは正しい世界にいません"
you-must-wait: "&cそのコマンドを再度実行するには、[number]秒を待つ必要があります。"
must-be-positive-number: "&c [number]は有効な正数ではありません。"
insufficient-rank: "&c ランクは十分に高くありません! (&7 [rank]&c )"
player-is-not-owner: "&b [name] &c は島の所有者ではありません!"
tips:
changing-obsidian-to-lava: 黒曜石を溶岩に戻します。注意してください!
not-on-island: "&c あなたは島にいません!"
worlds:
overworld: オーバーワールド
nether: ネザー
the-end: 終わり
tips:
changing-obsidian-to-lava: 黒曜石を溶岩に戻します。注意してください!
commands:
help:
header: "&7=========== &c[label]の ヘルプ &7==========="
@ -47,33 +51,35 @@ commands:
help:
description: 管理者コマンド
resets:
description: プレーヤーのリセットを編集する
description: プレーヤーのリセットを編集する
set:
description: このプレーヤーのリセットを設定します
description: このプレイヤーが自分の島をリセットした回数を設定します
parameters: "<プレーヤー> <リセット>"
success: "&a&b [name]&aのリセットを&b [number]&aに正常に設定します。"
success: "&b [name]&a の島のリセット数は &b [number]&a になりました。"
reset:
description: このプレーヤーのリセットを0にリセットします
description: プレイヤーの島のリセットカウントを0に設定します
parameters: "<プレーヤー>"
success-everyone: "&a&beveryone&aのリセットを&b0&aに正常にリセットします。"
success: "&a&b [name]&aのリセットを&b0&aに正常にリセットします。"
success-everyone: "&a &bみんな&a のリセット カウントを &b 0&a に正常にリセットしました。"
success: "&a &b [name]&a のリセット カウントを &b 0&a に正常にリセットしました。"
add:
description: プレーヤーにリセットを追加します
description: このプレイヤーの島リセット数を追加します
parameters: "<プレーヤー> <リセット>"
success: "&a&b [number]&aresetsを&b [name]に追加し、合計を&b [total]&a resetsに増やしました。"
remove:
description: プレーヤーのリセットを削除します
description: プレイヤーの島のリセット回数を減らします
parameters: "<プレーヤー> <リセット>"
success: "&a&b [number]&aresetsを&b [name]に削除し、合計を&b [total]&a resetsに減らしました。"
success: "&a &b [番号] &a リセットが &b [名前] の島&a から正常に削除され、合計が &b[合計]&a リセットに減少しました。"
purge:
parameters: "[日]"
description: "[日]以上放棄された島をパージする"
days-one-or-more: 1日以上必要です
purgable-islands: "[number]個のパーガブル島が見つかりました。"
purge-in-progress: "&cパージ中です。キャンセルするにはパージ停止を使用します"
number-error: "&cArgumentは日数でなければなりません"
confirm: "&dType [label] purge confirmでパージを開始します"
completed: "&aパージを停止しました"
see-console-for-status: パージが開始されました。ステータスについてはコンソールをご覧ください
no-purge-in-progress: "&c現在進行中のパージはありません。"
protect:
description: アイランドパージ保護の切り替え
move-to-island: "&c最初に島に移動してください"
@ -86,12 +92,11 @@ commands:
unowned:
description: 未所有の島を削除-確認が必要
unowned-islands: "&d[number]島を見つけました。"
days-one-or-more: 1日以上必要です
no-purge-in-progress: "&c現在進行中のパージはありません。"
status:
description: パージのステータスを表示します
status: "&bパージされた[purgeable] 個の島のうち[purged]個の島 &7(&b[percentage] %&7)&a."
team:
description: チームを管理する
add:
parameters: "<所有者> <プレーヤー>"
description: リーダーのチームにプレイヤーを追加する
@ -104,6 +109,15 @@ commands:
use-disband-owner: リーダーじゃない!解散を使用 [owner]
disbanded: 管理者はあなたのチームを解散!
success: "&b [name]&aのチームは解散しました。"
fix:
description: データベース内のクロスアイランドメンバーシップをスキャンして修正
scanning: データベースをスキャンしています...
duplicate-owner: "&c プレイヤーはデータベース内に複数の島を所有しています: [名前]"
player-has: "&cプレイヤー[name]には[number]の島があります"
duplicate-member: "&cプレーヤー[name]はデータベース内の複数の島のメンバーです"
rank-on-island: "&c [rank]島の[xyz]"
fixed: "&a修正済み"
done: "&aスキャン"
kick:
parameters: "<チームのプレーヤー>"
description: チームからプレーヤーを外す。
@ -116,17 +130,12 @@ commands:
description: プレーヤーをチームのリーダーにする%
already-owner: "&cプレイヤーはすでにリーダーです!"
success: "&b [name]&aがこの島の所有者になりました。"
fix:
description: データベース内のクロスアイランドメンバーシップをスキャンして修正
scanning: データベースをスキャンしています...
duplicate-owner: "&c プレイヤーはデータベースに複数の島を所有しています:[name]"
player-has: "&cプレイヤー[name]には[number]の島があります"
fixed: "&a修正済み"
done: "&aスキャン"
duplicate-member: "&cプレーヤー[name]はデータベース内の複数の島のメンバーです"
rank-on-island: "&c [rank]島の[xyz]"
range:
description: 管理島の範囲コマンド
invalid-value:
too-low: "&c保護範囲は&b 1&cより大きくなければなりません"
too-high: "&c保護範囲は&b[number]&c以下である必要があります"
same-as-before: "&c保護範囲はすでに&b [number]&cに設定されています"
display:
already-off: "&cインジケーターは既にオフです"
already-on: "&cインジケーターは既に"
@ -142,18 +151,14 @@ commands:
description: 島の保護範囲を設定します
success: "&2島の保護範囲を [number]に設定します。"
invalid-value:
not-numeric: "&c[number]は整数ではありません!"
too-high: "&c保護範囲は [number]と同じかそれ以下である必要があります。"
too-low: "&c保護範囲は1より大きくなければなりません"
same-as-before: "&c保護範囲はすでに [number]に設定されています!"
not-numeric: "&c[number]は整数ではありません!"
too-high: "&c保護範囲は [number]と同じかそれ以下である必要があります。"
reset:
parameters: "<プレーヤー>"
description: 世界のデフォルトに島の保護された範囲をリセットします
success: "&2島の保護範囲を [number] にリセット"
invalid-value:
too-low: "&c保護範囲は&b 1&cより大きくなければなりません"
too-high: "&c保護範囲は&b[number]&c以下である必要があります"
same-as-before: "&c保護範囲はすでに&b [number]&cに設定されています"
add:
description: 島の保護範囲を拡大
parameters: "<プレーヤー> <範囲>"
@ -179,19 +184,24 @@ commands:
info:
parameters: "<プレーヤー>"
description: あなたがどこにいるか、プレイヤーの島に関する情報を取得する
no-island: "&cあなたは今島にいません..."
no-island: "&c あなたは今島にいません..."
title: " ========== 島情報 ============"
island-uuid: 'UUID: [uuid]'
owner: '所有者: [owner] ([uuid])'
last-login: '最終ログイン: [date]'
last-login-date-time-format: EEE MMM dd HH:mm:ss zzz yyyy
deaths: '死亡: [number]'
resets-left: 'リセット: [number] (最大: [total])'
team-members-title: チームメンバー
team-owner-format: "&a [name] [rank]"
team-member-format: "&b [name] [rank]"
island-protection-center: 保護地域センター:[xyz]
island-center: 島の中心:[xyz]
island-coords: " 島座標: [xz1] - [xz2]"
islands-in-trash: "&dプレーヤーにはゴミ箱があります。"
protection-range: '保護範囲: [range]'
protection-range-bonus-title: "&b 以下の特典が含まれます:"
protection-range-bonus: 'ボーナス: [number]'
purge-protected: 島はパージ保護されています
max-protection-range: 最大の歴史的保護範囲:[range]
protection-coords: '保護座標: [xz1] - [xz2]'
@ -200,13 +210,11 @@ commands:
banned-format: "&c[name]"
unowned: 所有
island-location: '島の位置: [xyz]'
island-protection-center: 保護地域センター:[xyz]
island-center: 島の中心:[xyz]
switch:
description: 保護バイパスのオン/オフを切り替えます
op: "&cオップは常に保護をバイパスできます。コマンドを使用しないようにします。"
removing: 保護バイパスを削除しています...
adding: 保護バイパスを追加しています...
removing: "&a 保護バイパスを削除しています..."
adding: "&a 保護バイパスを追加しています..."
switchto:
parameters: "<プレイヤー> <番号>"
description: プレイヤーの島をゴミ箱にある番号付きの島に切り替える
@ -248,12 +256,27 @@ commands:
unknown-rank: "&c不明ランク!"
not-possible: "&cランクは訪問者より高くなければなりません"
rank-set: "&2[from] から [to] に設定されたランク。"
setprotectionlocation:
parameters: "[x y z coords]"
description: 現在地または[x y z]を島の保護地域の中心として設定します
island: "&cこれは、「[name]」が所有する[xyz]の島に影響します。"
confirmation: "&c [xyz]を保護センターとして設定してもよろしいですか?"
success: "&a [xyz]を保護センターとして正常に設定しました。"
fail: "&c [xyz] を保護センターとして設定できませんでした。"
island-location-changed: "&a [user]は島の保護センターを[xyz]に変更しました。"
xyz-error: "&c 3つの整数座標を指定します100 120 100"
setspawn:
description: この世界のスポーンとして島を設定します
already-spawn: "&cこの島はすでに出現しています"
no-island-here: "&cここには島はありません。"
confirmation: "&cこの島をこの世界のスポーンとして設定してもよろしいですか"
success: "&aこの島をこの世界のスポーンに設定しました。"
setspawnpoint:
description: この島のスポーンポイントとして現在の場所を設定します
no-island-here: "&cここには島はありません。"
confirmation: "&cこの場所をこの島のスポーンポイントとして設定してもよろしいですか"
success: "&aこの場所をこの島のスポーンポイントとして正常に設定しました。"
island-spawnpoint-changed: "&a [user] が島のスポーンポイントを変更しました。"
settings:
parameters: "[プレーヤー]"
description: プレーヤーのシステム設定またはアイランド設定を開きます
@ -279,6 +302,14 @@ commands:
copy:
parameters: "[air]"
description: pos1とpos2で設定されたクリップボードと、オプションでエアブロックをコピーします
delete:
parameters: "<名前>"
description: ブループリントを削除する
no-blueprint: "&b [name]&cは存在しません。"
confirmation: |
&cこのブループリントを削除してもよろしいですか
&c一度削除すると、それを回復する方法はありません。
success: "&aブループリントが正常に削除されました&b [name]&a。"
load:
parameters: "<名前>"
description: 設計図をクリップボードに読み込みます
@ -298,6 +329,11 @@ commands:
save:
parameters: "<青写真の名前>"
description: コピーしたクリップボードを保存します
rename:
parameters: "<設計図名> <新しい名前>"
description: ブループリントの名前を変更する
success: "&aブループリント&b [old]&aは&b [name]&aに正常に名前変更されました。"
pick-different-name: "&cブループリントの現在の名前とは異なる名前を指定してください。"
management:
back: バック
instruction: 設計図をクリックして、ここをクリックしてください
@ -310,9 +346,13 @@ commands:
青写真を配置
設定する権利
trash: ゴミ箱
no-trash: ゴミ箱に入れることはできません
trash-instructions: ここをクリックして削除します
no-trash-instructions: デフォルトのバンドルを破棄できません
permission: 許可
no-permission: 無許可
perm-required: 必須
no-perm-required: デフォルトのバンドルに権限を設定することはできません
perm-not-required: 必須ではありません
perm-format: "&e"
remove: 右クリックして削除
@ -328,7 +368,8 @@ commands:
prompt: 名前を入力するか、「quit」で終了します
too-long: "&c長すぎる"
pick-a-unique-name: よりユニークな名前を選んでください
invalid-char-in-unique-name: "Unique name cannot contain, start, or end with special characters, neither contain number! "
stripped-char-in-unique-name: "&c 一部の文字は許可されていないため削除されました。 &a 新しい ID は &b
[名前]&a になります。"
success: 成功!
conversation-prefix: ">"
description:
@ -342,26 +383,9 @@ commands:
slot-instructions: |
&a左クリックして増加
&a右クリックして減少
end: The End
nether: ネザー
normal: 普通
no-trash: ゴミ箱に入れることはできません
no-trash-instructions: デフォルトのバンドルを破棄できません
no-permission: 無許可
no-perm-required: デフォルトのバンドルに権限を設定することはできません
delete:
parameters: "<名前>"
description: ブループリントを削除する
no-blueprint: "&b [name]&cは存在しません。"
confirmation: |
&cこのブループリントを削除してもよろしいですか
&c一度削除すると、それを回復する方法はありません。
success: "&aブループリントが正常に削除されました&b [name]&a。"
rename:
parameters: "<設計図名> <新しい名前>"
description: ブループリントの名前を変更する
success: "&aブループリント&b [old]&aは&b [name]&aに正常に名前変更されました。"
pick-different-name: "&cブループリントの現在の名前とは異なる名前を指定してください。"
nether: ネザー
end: The End
resetflags:
parameters: "[flag]"
description: すべての島をconfig.ymlのデフォルトのフラグ設定にリセットします
@ -375,11 +399,15 @@ commands:
description: プレイヤーの島を削除します。
cannot-delete-owner: "&cすべての島のメンバーは、それを削除する前に島から追い出される必要があります。"
deleted-island: "&2[xyz] の島は正常に削除されました。"
deletehomes:
parameters: "<プレイヤー>"
description: 名前付きの家をすべて島から削除します
warning: "&c 名前付きの家はすべて島から削除されます。"
why:
parameters: "<プレイヤー>"
description: コンソール保護デバッグレポートの切り替え
turning-on: "[name]のコンソールデバッグをオンにします。"
turning-off: "[name]のコンソールデバッグをオフにします。"
turning-on: "&b [name]&a のコンソール デバッグをオンにします。"
turning-off: "&b [name]&a のコンソール デバッグをオフにします。"
deaths:
description: プレイヤーの死を編集する
reset:
@ -400,29 +428,19 @@ commands:
description: プレイヤーの死を取り除く
parameters: "<プレイヤー> <死>"
success: "&a&b [number]&adeathsを&b [name]に正常に削除し、合計を&b [total]&a deathsに減らしました。"
resetname:
description: プレイヤーの島名をリセットする
success: "&a [name] の島名が正常にリセットされました。"
clearresets:
parameters: "<プレーヤー>"
description: この世界のプレーヤーリセットカウントをクリアします。
cleared: "&2リセット解除"
description: この世界のプレーヤーリセットカウントをクリアします。
clearresetsall:
description: この世界のプレーヤーリセットカウントをすべてクリアします。
setspawnpoint:
description: この島のスポーンポイントとして現在の場所を設定します
no-island-here: "&cここには島はありません。"
confirmation: "&cこの場所をこの島のスポーンポイントとして設定してもよろしいですか"
success: "&aこの場所をこの島のスポーンポイントとして正常に設定しました。"
island-spawnpoint-changed: "&a [user]はこの島のスポーンポイントを変更しました。"
setprotectionlocation:
parameters: "[x y z coords]"
description: 現在地または[x y z]を島の保護地域の中心として設定します
island: "&cこれは、「[name]」が所有する[xyz]の島に影響します。"
confirmation: "&c [xyz]を保護センターとして設定してもよろしいですか?"
success: "&a [xyz]を保護センターとして正常に設定しました。"
fail: "&a [xyz]を保護センターとして設定できませんでした。"
island-location-changed: "&a [user]は島の保護センターを[xyz]に変更しました。"
xyz-error: "&c 3つの整数座標を指定します100 120 100"
bentobox:
description: BentoBox管理コマンド
perms:
description: BentoBox とアドオンの有効な権限を YAML 形式で表示します
about:
description: 著作権とライセンス情報を表示する
reload:
@ -477,8 +495,8 @@ commands:
description: あなたの島にテレポート
teleport: "&a島にテレポート"
teleported: "&aテレポート #[number]をホームにします。"
tip: "&bヘルプの種類/[label]ヘルプを表示します。"
unknown-home: "&c不明な家の名前"
tip: "&bヘルプの種類/[label]ヘルプを表示します。"
help:
description: 本島のコマンド
pick-world: "&c[worlds]からワールドを指定する"
@ -490,19 +508,25 @@ commands:
description: 島を作成する
parameters: "<青写真>"
too-many-islands: "&cこの世界には島が多すぎます。あなたの島を作成するのに十分なスペースがありません。"
cannot-create-island: "&c時間内にスポットが見つかりませんでした。もう一度お試しください..."
unable-create-island: 島を生成することができませんでした, 管理者に連絡してください.
creating-island: "&aあなたの島の場所を見つけました。あなたのために準備しましょう。"
pasting:
estimated-time: "&a推定時間&b [number]s。"
blocks: "&a ブロックごとに構築します。 合計&b[numbber]&aブロック。"
entities: "&aそれを生き物で満たす。 合計&b[number]&a体のクリーチャー。"
dimension-done: "&a [world]に島が建設されます。"
done: "&a完了しました。あなたの島の準備が整い、あなたを待っています"
pick: "&2島を選ぶ"
unknown-blueprint: "&cそのブループリントはまだロードされていません。"
on-first-login: "&aWelcome数秒で島の準備を開始します。"
pick-world: 世界から選ぶ [worlds]
cannot-create-island: "&c時間内にスポットが見つかりませんでした。もう一度お試しください..."
you-can-teleport-to-your-island: "&a必要なときに島にテレポートできます。"
pick-world: 世界から選ぶ [worlds]
deletehome:
description: 自宅の場所を削除する
parameters: "[家名]"
homes:
description: 自分の家をリストアップする
info:
description: 島についての情報を表示
parameters: "<プレイヤー>"
@ -533,7 +557,10 @@ commands:
sethome:
description: ホームテレポートポイントを設定する
must-be-on-your-island: あなたの島に家を設定する必要があります!
too-many-homes: "&c設定できません-あなたの島は最大[number]の家にあります。"
home-set: あなたの島の家はあなたの現在の場所に設定されています。
homes-are: "&6島の家は次のとおりです:"
home-list-syntax: "&6 [name]"
nether:
not-allowed: "&cあなたはネザーにあなたの家を設定することはできません。"
confirmation: "&cネザーにあなたの家を設定しますか"
@ -541,9 +568,6 @@ commands:
not-allowed: "&c最後に家を設定することはできません。"
confirmation: "&c最後に家を設定してもよろしいですか"
parameters: "[数]"
too-many-homes: "&c設定できません-あなたの島は最大[number]の家にあります。"
homes-are: "&6島の家は次のとおりです:"
home-list-syntax: "&6 [name]"
setname:
description: 島の名前を設定します
name-too-short: 短すぎる。最小サイズは [number] 文字です。
@ -551,6 +575,11 @@ commands:
name-already-exists: "&cこのゲームモードでは、その名前の島がすでに存在します。"
parameters: "<名前>"
success: "&a島の名前を&b [name]&aに正常に設定しました。"
renamehome:
description: 自宅の場所の名前を変更する
parameters: "[家名]"
enter-new-name: "&6新しい名前を入力してください"
already-exists: "&cその名前はすでに存在します。別の名前を試してください。"
resetname:
description: 島の名前をリセット
success: "&a島の名前を正常にリセットしました。"
@ -581,7 +610,7 @@ commands:
already-has-rank: プレイヤーはすでにランクを持っている!
you-are-a-coop-member: あなたは [name]に閉じこもっれた
success: "&b[name]&aを協力メンバーにしました"
name-has-invited-you: "&a [name]はあなたを彼らの島の協同組合員になるよう招待しました。"
name-has-invited-you: "&a [name] はあなたを彼らの島の協力メンバーとして招待しています。"
paramters: "<プレーヤー>"
uncoop:
description: プレイヤーから生協のランクを削除する
@ -592,19 +621,19 @@ commands:
you-are-no-longer-a-coop-member: あなたはもはや[name]の島の生協のメンバーではない
all-members-logged-off: "&cすべての島のメンバーがログオフしたため、あなたはもはや[name]の島の協同組合員ではありません"
success: "&b [name]&aisはもはやあなたの島の協同組合員ではありません。"
paramters: "<プレーヤー>"
is-full: "&cこれ以上生協メンバーを追加することはできません"
paramters: "<プレーヤー>"
trust:
description: 島でプレイヤーに信頼できるランクを与える
parameters: "<プレイヤー>"
trust-in-yourself: 自分を信頼して!
name-has-invited-you: "&a [name]は、あなたを彼らの島の信頼できるメンバーになるよう招待しています。"
name-has-invited-you: "&a [name] は、あなたを島の信頼できるメンバーとして招待しています。"
player-already-trusted: プレイヤーはすでに信頼されている!
you-are-trusted: "[name]はあなたを信頼!"
success: "&a信頼済み&b [name]&a。"
paramters: "<プレーヤー>"
is-full: "&c 他人を信頼することはできません。背後に注意!"
members-trusted: メンバは既に信頼されています
is-full: "&c他の人を信頼することはできません。"
paramters: "<プレーヤー>"
untrust:
description: プレイヤーから信頼できるプレイヤーランクを削除する
parameters: "<プレイヤー>"
@ -651,19 +680,24 @@ commands:
kick:
description: 島からメンバーを削除する
parameters: "<プレーヤー>"
owner-kicked: "&c [gamemode]で所有者があなたを島から追い出しました!"
player-kicked: "&c [gamemode] で [name] によってあなたは島から追い出されました!"
cannot-kick: 自分を削除することはできません!
cannot-kick-rank: "&c あなたのランクでは [名前] をキックすることはできません!"
success: "&b [name]&aはあなたの島から追い出されました。"
demote:
description: ランクダウンあなたの島のプレーヤーを降格
parameters: "<プレーヤー>"
errors:
cant-demote-yourself: "&c自分を降格することはできません"
cant-demote: "&c 上位ランクを降格させることはできません。"
failure: プレイヤーはこれ以上降格することはできません!
success: "[name]を[rank]に降格"
promote:
description: ランク上のあなたの島のプレーヤーを促進しなさい
parameters: "<プレーヤー>"
errors:
cant-promote-yourself: "&c 自分自身を宣伝することはできません。"
cant-promote: "&c 自分のランク以上に昇進することはできません。"
failure: プレイヤーはこれ以上昇格することはできません!
success: "[name]を[rank]に昇格"
setowner:
@ -714,14 +748,6 @@ commands:
not-on-island: "&cそのプレイヤーはあなたの島にいません"
player-expelled-you: "&b [name]&cはあなたを島から追放しました"
success: "&a島から&b [name]&aを追放した。"
deletehome:
description: 自宅の場所を削除する
parameters: "[家名]"
renamehome:
description: 自宅の場所の名前を変更する
parameters: "[家名]"
enter-new-name: "&6新しい名前を入力してください"
already-exists: "&cその名前はすでに存在します。別の名前を試してください。"
ranks:
owner: 所有者
sub-owner: サブ所有者
@ -735,6 +761,16 @@ ranks:
protection:
command-is-banned: コマンドは、訪問者のために禁止され
flags:
ALLAY:
name: アレイ相互作用
description: Allay との間でアイテムの授受を許可する
hint: アレイインタラクションが無効になっています
ANIMAL_NATURAL_SPAWN:
description: 自然な動物の産卵を切り替えます
name: 動物の自然なスポーン
ANIMAL_SPAWNERS_SPAWN:
description: 産卵者と動物の産卵を切り替える
name: 動物の産卵者
ANVIL:
description: トグル使用
name: 金床
@ -743,6 +779,10 @@ protection:
description: トグル使用
name: アーマースタンド
hint: アーマースタンド使用不可
AXOLOTL_SCOOPING:
name: ウーパールートルすくい
description: バケツを使ってウーバーイーツをすくえるようにする
hint: ウーパールーパーすくいが無効になっています
BEACON:
description: トグル使用
name: ビーコン
@ -755,10 +795,28 @@ protection:
name: ボート
description: ボートの相互作用の切り替え
hint: ボートの相互作用は許可されていません
BOOKSHELF:
name: 本棚
description: |-
&a 本の配置を許可する
&a または本を受け取ります。
hint: 本を置いたり、本を取ったりすることはできません。
BREAK_BLOCKS:
description: 破断ブロックの切り替え
name: ブレークブロック
hint: ブロックの破損を無効
BREAK_SPAWNERS:
description: |-
スポナーの破壊を切り替えます。
BreakBlocksフラグをオーバーライドします。
name: スポナーを壊す
hint: スポナーブレーキングが無効
BREAK_HOPPERS:
description: |-
ホッパーの破損を切り替えます。
BreakBlocksフラグをオーバーライドします。
name: ホッパーを壊す
hint: ホッパーの破損が無効
BREEDING:
description: トグル繁殖
name: 繁殖動物
@ -791,6 +849,41 @@ protection:
&7 専用のフラグに
&7 よって処理されます。
hint: コンテナアクセスが無効です
CHEST:
name: 箪笥
description: トグル使用
hint: 箪笥アクセス不可
BARREL:
name: バレル
description: バレルのインタラクションを切り替えます
hint: バレルアクセス無効
BLOCK_EXPLODE_DAMAGE:
description: |-
&a ベッドとリスポーンアンカーを許可する
&aでブロックを壊してダメージを与える
&a エンティティ。
name: 爆発ダメージをブロック
COMPOSTER:
name: コンポスター
description: コンポスターのインタラクションを切り替えます
hint: コンポスターインタラクションが無効になっています
FLOWER_POT:
name: 植木鉢
description: 植木鉢のインタラクションを切り替えます
hint: 植木鉢のインタラクションが無効になっています
SHULKER_BOX:
name: シュルカーボックス
description: シュルカーボックスのインタラクションを切り替えます
hint: シュルカーボックスへのアクセスが無効になります
SHULKER_TELEPORT:
description: |-
&a シュルカーはテレポートできる
&a アクティブな場合。
name: シュルカーのテレポート
TRAPPED_CHEST:
name: トラップチェスト
description: トラップされたチェストのインタラクションを切り替えます
hint: トラップチェストへのアクセスが無効になりました
DISPENSER:
name: ディスペンサー
description: ディスペンサーインタラクションの切り替え
@ -835,6 +928,12 @@ protection:
description: 水を集めるトグル
name: 水を集める
hint: 水バケツ無効
COLLECT_POWDERED_SNOW:
description: |-
&a 粉雪の収集を切り替えます
&a (バケットをオーバーライド)
name: 粉雪を集めます
hint: 粉雪バケツは無効です
COMMAND_RANKS:
name: "&eコマンドランク"
description: コマンドランクの設定
@ -849,6 +948,10 @@ protection:
description: トグルクリーパー苦情
name: クリーパー苦情
hint: クリーパーグリーフィングが無効
CROP_PLANTING:
description: "&a 種を植えることができる人を設定します。"
name: 作物の植え付け
hint: 作物の植え付けが禁止されている
CROP_TRAMPLE:
description: クロップ踏みつけを切り替える
name: 作物を踏みにじる
@ -891,6 +994,11 @@ protection:
&aエンダーマンはブロックを
&a削除することができます
name: エンダーマン苦情
ENDERMAN_TELEPORT:
description: |-
&a エンダーマンはテレポートできる
&a アクティブな場合。
name: エンダーマンテレポート
ENDER_PEARL:
description: トグル使用
name: エンダーパール
@ -950,6 +1058,17 @@ protection:
&a終了するモンスターを
&a削除
name: "&e生き物を島に限る"
HARVEST:
description: |-
&a 作物を収穫できる人を設定します。
&a アイテムを許可することを忘れないでください
&ピックアップも!
name: 作物の収穫
hint: 作物の収穫が無効になっています
HIVE:
description: "&aハイブの収穫を切り替えます。"
name: ハイブの収穫
hint: 収穫が無効
HURT_ANIMALS:
description: トグルを傷つける
name: 動物を傷つける
@ -998,10 +1117,28 @@ protection:
LEASH:
description: トグル使用
name: ひもの使用
LECTERN:
name: 演台
description: |-
&a書見台に本を置くことを許可する
&aまたはそれから本を取ります。
&cそれはプレイヤーが
&c本を読んでいます。
hint: 書見台に本を置いたり、書見台から本を取り出したりすることはできません。
LEVER:
description: トグル使用
name: レバー使用
hint: レバー使用不可
LIMIT_MOBS:
description: |-
&aこのゲームモードで
&aエンティティが
&aスポーンするのを
&a制限します。
name: "&eエンティティタイプのスポーンを制限する"
can: "&aスポーンできます"
cannot: "&cスポーンできません"
LIQUIDS_FLOWING_OUT:
name: 島の外を流れる液体
description: |-
@ -1020,6 +1157,11 @@ protection:
LOCK:
description: トグル使用
name: ロック島
CHANGE_SETTINGS:
name: 設定を変更する
description: |-
&a メンバーの切り替えを許可します
&a ロールは島の設定を変更できます。
MILKING:
description: トグル牛搾乳
name: 搾乳
@ -1028,6 +1170,12 @@ protection:
name: トロッコ
description: トロッコの相互作用の切り替え
hint: トロッコの操作が無効になっています
MONSTER_NATURAL_SPAWN:
description: 自然モンスターの産卵を切り替えます
name: モンスターナチュラルスポーン
MONSTER_SPAWNERS_SPAWN:
description: スポナーとモンスターのスポーンを切り替えます
name: モンスタースポナー
MOUNT_INVENTORY:
description: アクセスの切り替え
name: 在庫のマウント
@ -1074,6 +1222,13 @@ protection:
&aMayは遅延の削減に役立ちます。
スポーン島には影響しません。
name: オフラインレッドストーン
PETS_STAY_AT_HOME:
description: |-
&aアクティブなとき、飼いならされたペット
&aはとにのみ行くことができます
&aは所有者を離れることはできません
&aホームアイランド。
name: ペットは家にいる
PISTON_PUSH:
description: |-
&aこのオプションを有効にすると、
@ -1119,9 +1274,9 @@ protection:
description: PVP を有効/無効にする
name: PVP
hint: "&cPVPはオーバーワールドで無効になっています"
active: PVP はここでアクティブです!
enabled: "&cオーバーワールドのPVPが有効になりました。"
disabled: "&aオーバーワールドのPVPが無効になりました。"
active: PVP はここでアクティブです!
REDSTONE:
description: トグル使用
name: レッドストーンアイテム
@ -1155,6 +1310,24 @@ protection:
&a変更を許可します卵を産卵します。
name: スポナーにスポーンエッグ
hint: スポーンエッグを使用したスポナーのエンティティタイプの変更は許可されていません
SCULK_SENSOR:
description: |-
&a スカルクセンサーを切り替えます
&A のアクティベーション。
name: スカルクセンサー
hint: スカルクセンサーのアクティベーションが無効になっています
SCULK_SHRIEKER:
description: |-
&a スカルクシュリーカーを切り替えます
&A のアクティベーション。
name: スカルク・シュリーカー
hint: スカルクシュリーカーのアクティベーションが無効になっています
SIGN_EDITING:
description: |-
&a テキスト編集を許可します
&A の記号
name: サイン編集
hint: サイン編集は無効になっています
TNT_DAMAGE:
description: |-
&aTNTおよびTNTトロッコが
@ -1201,91 +1374,63 @@ protection:
&aコマンドを使用して島に戻る
&a落下している場合。
hint: "&c落下中はできません。"
VISITOR_KEEP_INVENTORY:
name: 訪問者は死亡時の在庫を保管します
description: |-
&a プレイヤーがカードを紛失しないようにします
&a アイテムと経験値が死亡した場合
&a 彼らが訪問者である島。
&a
&a アイランドのメンバーはまだアイテムを失っています
そして、彼らが自分の島で死んだ場合!
VISITOR_TRIGGER_RAID:
name: 訪問者が襲撃を引き起こす
description: |-
&a 訪問者が開始できるかどうかを切り替えます
&a 彼らがいる島への襲撃
&訪問中。
&a
&a Bad Omen効果が削除されます!
ENTITY_PORTAL_TELEPORT:
name: エンティティポータルの使用法
description: |-
&a エンティティ (非プレイヤー) ができるかどうかを切り替えます。
&a ポータルを使用して間をテレポートします
寸法(&A)
WITHER_DAMAGE:
name: 許可/禁止
description: |-
&aアクティブな場合、枯れます
&aブロックとプレイヤーを破損
ANIMAL_SPAWN:
description: 産卵の切り替え
name: 動物の産卵
CHEST:
description: トグル使用
hint: 箪笥アクセス不可
name: 箪笥
FIRE:
description: 火災が存在するかどうかを許可する
hint: 火は許されない
name:
MONSTER_SPAWN:
description: 産卵の切り替え
name: モンスターの産卵
TNT:
name: TNT の損傷
description: TNT のダメージを切り替える
PORTAL:
name: ポータル
hint: ポータルの使用は許可されない
description: トグル使用
ANIMAL_NATURAL_SPAWN:
description: 自然な動物の産卵を切り替えます
name: 動物の自然なスポーン
ANIMAL_SPAWNERS_SPAWN:
description: 産卵者と動物の産卵を切り替える
name: 動物の産卵者
BREAK_SPAWNERS:
WORLD_BLOCK_EXPLODE_DAMAGE:
description: |-
スポナーの破壊を切り替えます。
BreakBlocksフラグをオーバーライドします。
name: スポナーを壊す
hint: スポナーブレーキングが無効
BREAK_HOPPERS:
description: |-
ホッパーの破損を切り替えます。
BreakBlocksフラグをオーバーライドします。
name: ホッパーを壊す
hint: ホッパーの破損が無効
LECTERN:
name: 演台
description: |-
&a書見台に本を置くことを許可する
&aまたはそれから本を取ります。
&cそれはプレイヤーが
&c本を読んでいます。
hint: 書見台に本を置いたり、書見台から本を取り出したりすることはできません。
LIMIT_MOBS:
description: |-
&aこのゲームモードで
&aエンティティが
&aスポーンするのを
&a制限します。
name: "&eエンティティタイプのスポーンを制限する"
can: "&aスポーンできます"
cannot: "&cスポーンできません"
MONSTER_NATURAL_SPAWN:
description: 自然モンスターの産卵を切り替えます
name: モンスターナチュラルスポーン
MONSTER_SPAWNERS_SPAWN:
description: スポナーとモンスターのスポーンを切り替えます
name: モンスタースポナー
&a ベッドとリスポーンアンカーを許可する
&aでブロックを壊してダメージを与える
&a 島の境界外のエンティティ。
name: ワールドブロック爆発ダメージ
WORLD_TNT_DAMAGE:
description: |-
&aTNTおよびTNTトロッコを許可する
&aブロックを壊してダメージを与える
&a島の制限外のエンティティ。
name: 世界のTNTダメージ
PETS_STAY_AT_HOME:
description: |-
&aアクティブなとき、飼いならされたペット
&aはとにのみ行くことができます
&aは所有者を離れることはできません
&aホームアイランド。
name: ペットは家にいる
HIVE:
description: "&aハイブの収穫を切り替えます。"
name: ハイブの収穫
hint: 収穫が無効
PORTAL:
description: トグル使用
hint: ポータルの使用は許可されない
name: ポータル
FIRE:
name:
description: 火災が存在するかどうかを許可する
hint: 火は許されない
ANIMAL_SPAWN:
description: 産卵の切り替え
name: 動物の産卵
MONSTER_SPAWN:
description: 産卵の切り替え
name: モンスターの産卵
TNT:
description: TNT のダメージを切り替える
name: TNT の損傷
locked: 島はロックされている!
protected: '島保護: [description]'
world-protected: "&c世界保護: [description]"
@ -1458,31 +1603,6 @@ catalog:
&aBentoBoxでGitHubに接続できるようにする
設定を変更するか、後で再試行してください。
panel:
credits:
title: "&8 [name]&2クレジット"
contributor:
name: "&a[name]"
description: "&aCommits&b [commits]\n"
empty-here:
name: "&cこれはここでは空に見えます..."
description: |
&cBentoBoxは貢献者を収集できませんでした
このアドオン用。
&aBentoBoxでGitHubに接続できるようにする
設定を変更するか、後で再試行してください。
successfully-loaded: |-
&6 ____ _ ____
&6 | _ \ | | | _ \ &7by &atastybento &7and &aPoslovitch
&6 | |_) | ___ _ __ | |_ ___ | |_) | _____ __ &72017 - 2022
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ /
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &bv&e[version]
&6 |____/ \___|_| |_|\__\___/|____/ \___/_/\_\ &8Loaded in &e[time]&8ms.
prefixes:
bentobox: "&6 BentoBox &7 &l > &r "
enums:
DamageCause:
CONTACT: 衝突
@ -1513,3 +1633,25 @@ enums:
HOT_FLOOR: ホットフロア
CRAMMING: 一夜漬け
DRYOUT: 完全に乾く
panel:
credits:
title: "&8 [name]&2クレジット"
contributor:
name: "&a[name]"
description: "&aCommits&b [commits]\n"
empty-here:
name: "&cこれはここでは空に見えます..."
description: |
&cBentoBoxは貢献者を収集できませんでした
このアドオン用。
&aBentoBoxでGitHubに接続できるようにする
設定を変更するか、後で再試行してください。
successfully-loaded: |2
&6 ____ _ ____
&6 | _ \ | | | _ \ &7 by &a tastybento &7 と &a Poslovitch
&6 | |_) | ____ | |_ ___ | |_) | ______ __ &7 2017 - 2023
&6 | _ < / _ \ '_ \| __/ _ \| _ < / _ \ \/ /
&6 | |_) | __/ | | | || (_) | |_) | (_) > < &b v&e [バージョン]
&6 |___/ \___|_| |_|\__\___/|____/ \___/_/\_\ &8 &e [time]&8 ミリ秒でロードされました。

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,210 @@
package world.bentobox.bentobox.blueprints;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.util.BoundingBox;
import org.bukkit.util.Vector;
import org.eclipse.jdt.annotation.NonNull;
import org.junit.After;
import org.junit.Before;
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.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.user.User;
/**
* @author tastybento
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({BentoBox.class, Bukkit.class})
public class BlueprintClipboardTest {
private BlueprintClipboard bc;
@Mock
private @NonNull Blueprint blueprint;
@Mock
private @NonNull User user;
@Mock
private BentoBox plugin;
@Mock
private World world;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
// Set up plugin
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
// User
when(user.getTranslation(Mockito.anyString())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class));
User.setPlugin(plugin);
bc = new BlueprintClipboard();
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
Mockito.framework().clearInlineMocks();
}
/**
* Test method for {@link world.bentobox.bentobox.blueprints.BlueprintClipboard#BlueprintClipboard(world.bentobox.bentobox.blueprints.Blueprint)}.
*/
@Test
public void testBlueprintClipboardBlueprint() {
bc = new BlueprintClipboard(blueprint);
assertNotNull(bc);
}
/**
* Test method for {@link world.bentobox.bentobox.blueprints.BlueprintClipboard#BlueprintClipboard()}.
*/
@Test
public void testBlueprintClipboard() {
assertNotNull(bc);
}
/**
* Test method for {@link world.bentobox.bentobox.blueprints.BlueprintClipboard#copy(world.bentobox.bentobox.api.user.User, boolean, boolean)}.
*/
@Test
public void testCopy() {
assertFalse(bc.copy(user, false, false));
verify(user, never()).sendMessage("commands.admin.blueprint.mid-copy");
verify(user).sendMessage("commands.admin.blueprint.need-pos1-pos2");
}
/**
* Test method for {@link world.bentobox.bentobox.blueprints.BlueprintClipboard#getVectors(org.bukkit.util.BoundingBox)}.
*/
@Test
public void testGetVectors() {
BoundingBox bb = new BoundingBox(10.5, 10.5, 10.5, 19.5, 19.5, 19.5);
List<Vector> list = bc.getVectors(bb);
assertEquals(1000, list.size());
bb = new BoundingBox(19.5, 19.5, 19.5, 10.5, 10.5, 10.5);
list = bc.getVectors(bb);
assertEquals(1000, list.size());
bb = new BoundingBox(-10.5, -10.5, -10.5, -19.5, -19.5, -19.5);
list = bc.getVectors(bb);
assertEquals(1000, list.size());
bb = new BoundingBox(-19.5, -19.5, -19.5, -10.5, -10.5, -10.5);
list = bc.getVectors(bb);
assertEquals(1000, list.size());
bb = new BoundingBox(-5.5, -5.5, -5.5, 3.5, 3.5, 3.5);
list = bc.getVectors(bb);
assertEquals(1000, list.size());
}
/**
* Test method for {@link world.bentobox.bentobox.blueprints.BlueprintClipboard#getOrigin()}.
*/
@Test
public void testGetOrigin() {
assertNull(bc.getOrigin());
}
/**
* Test method for {@link world.bentobox.bentobox.blueprints.BlueprintClipboard#getPos1()}.
*/
@Test
public void testGetPos1() {
assertNull(bc.getPos1());
}
/**
* Test method for {@link world.bentobox.bentobox.blueprints.BlueprintClipboard#getPos2()}.
*/
@Test
public void testGetPos2() {
assertNull(bc.getPos2());
}
/**
* Test method for {@link world.bentobox.bentobox.blueprints.BlueprintClipboard#isFull()}.
*/
@Test
public void testIsFull() {
assertFalse(bc.isFull());
}
/**
* Test method for {@link world.bentobox.bentobox.blueprints.BlueprintClipboard#setOrigin(org.bukkit.util.Vector)}.
*/
@Test
public void testSetOrigin() {
Vector v = new Vector(1,2,3);
bc.setOrigin(v);
assertEquals(v, bc.getOrigin());
}
/**
* Test method for {@link world.bentobox.bentobox.blueprints.BlueprintClipboard#setPos1(org.bukkit.Location)}.
*/
@Test
public void testSetPos1() {
Location l = new Location(world, 1,2,3);
bc.setPos1(l);
assertEquals(l, bc.getPos1());
}
/**
* Test method for {@link world.bentobox.bentobox.blueprints.BlueprintClipboard#setPos2(org.bukkit.Location)}.
*/
@Test
public void testSetPos2() {
Location l = new Location(world, 1,2,3);
bc.setPos2(l);
assertEquals(l, bc.getPos2());
}
/**
* Test method for {@link world.bentobox.bentobox.blueprints.BlueprintClipboard#getBlueprint()}.
*/
@Test
public void testGetBlueprint() {
assertNull(bc.getBlueprint());
}
/**
* Test method for {@link world.bentobox.bentobox.blueprints.BlueprintClipboard#setBlueprint(world.bentobox.bentobox.blueprints.Blueprint)}.
*/
@Test
public void testSetBlueprint() {
bc.setBlueprint(blueprint);
assertEquals(blueprint, bc.getBlueprint());
}
}

View File

@ -0,0 +1,247 @@
package world.bentobox.bentobox.listeners.flags.clicklisteners;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
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 java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.Inventory;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.junit.After;
import org.junit.Before;
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 org.powermock.reflect.Whitebox;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.TabbedPanel;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.lists.Flags;
import world.bentobox.bentobox.managers.CommandsManager;
import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.bentobox.panels.settings.SettingsTab;
import world.bentobox.bentobox.util.Util;
/**
* @author tastybento
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({Bukkit.class, BentoBox.class, Util.class})
public class CommandRankClickListenerTest {
@Mock
private User user;
@Mock
private World world;
@Mock
private TabbedPanel panel;
@Mock
private BentoBox plugin;
@Mock
private IslandWorldManager iwm;
@Mock
private @NonNull Inventory inv;
@Mock
private GameModeAddon gma;
private CommandRankClickListener crcl;
@Mock
private Player player;
@Mock
private IslandsManager im;
@Mock
private @Nullable Island island;
private UUID uuid = UUID.randomUUID();
private RanksManager rm;
@Mock
private CommandsManager cm;
@Mock
private SettingsTab tab;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
// Bukkit
PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS);
// Set up plugin
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
// Island
when(island.getOwner()).thenReturn(uuid);
when(island.isAllowed(user, Flags.CHANGE_SETTINGS)).thenReturn(true);
when(island.getRankCommand(anyString())).thenReturn(RanksManager.MEMBER_RANK);
// IM
when(plugin.getIslands()).thenReturn(im);
when(im.getIsland(world, uuid)).thenReturn(island);
when(im.getIsland(world, user)).thenReturn(island);
// IWM
when(plugin.getIWM()).thenReturn(iwm);
when(iwm.getAddon(any())).thenReturn(Optional.of(gma));
when(iwm.getPermissionPrefix(world)).thenReturn("oneblock.");
// Panel
when(panel.getInventory()).thenReturn(inv);
when(panel.getWorld()).thenReturn(Optional.of(world));
when(panel.getName()).thenReturn("protection.flags.COMMAND_RANKS.name");
when(panel.getActiveTab()).thenReturn(tab);
// Tab
when(tab.getIsland()).thenReturn(island);
// User
when(user.getUniqueId()).thenReturn(uuid);
when(user.hasPermission(anyString())).thenReturn(true);
when(user.getPlayer()).thenReturn(player);
when(user.inWorld()).thenReturn(true);
when(user.getWorld()).thenReturn(world);
when(user.getTranslation(anyString())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class));
when(user.getTranslation(anyString(),anyString(),anyString())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class));
// Util
PowerMockito.mockStatic(Util.class, Mockito.CALLS_REAL_METHODS);
when(Util.getWorld(any())).thenReturn(world);
// RanksManager
rm = new RanksManager();
when(plugin.getRanksManager()).thenReturn(rm);
// Commands Manager
when(plugin.getCommandsManager()).thenReturn(cm);
Map<String, CompositeCommand> map = new HashMap<>();
CompositeCommand cc = mock(CompositeCommand.class);
when(cc.getWorld()).thenReturn(world);
when(cc.isConfigurableRankCommand()).thenReturn(true);
when(cc.getName()).thenReturn("test");
when(cc.getSubCommands()).thenReturn(Collections.emptyMap());
map.put("test", cc);
when(cm.getCommands()).thenReturn(map);
crcl = new CommandRankClickListener();
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
Mockito.framework().clearInlineMocks();
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.flags.clicklisteners.CommandRankClickListener#onClick(world.bentobox.bentobox.api.panels.Panel, world.bentobox.bentobox.api.user.User, org.bukkit.event.inventory.ClickType, int)}.
*/
@Test
public void testOnClickWrongWorld() {
when(user.inWorld()).thenReturn(false);
assertTrue(crcl.onClick(panel, user, ClickType.LEFT, 0));
verify(user).sendMessage("general.errors.wrong-world");
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.flags.clicklisteners.CommandRankClickListener#onClick(world.bentobox.bentobox.api.panels.Panel, world.bentobox.bentobox.api.user.User, org.bukkit.event.inventory.ClickType, int)}.
*/
@Test
public void testOnClickNoPermission() {
when(user.hasPermission(anyString())).thenReturn(false);
assertTrue(crcl.onClick(panel, user, ClickType.LEFT, 0));
verify(user).sendMessage("general.errors.no-permission", TextVariables.PERMISSION, "oneblock.settings.COMMAND_RANKS");
verify(player).playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F);
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.flags.clicklisteners.CommandRankClickListener#onClick(world.bentobox.bentobox.api.panels.Panel, world.bentobox.bentobox.api.user.User, org.bukkit.event.inventory.ClickType, int)}.
*/
@Test
public void testOnClickNoFlag() {
when(island.isAllowed(user, Flags.CHANGE_SETTINGS)).thenReturn(false);
assertTrue(crcl.onClick(panel, user, ClickType.LEFT, 0));
verify(user).sendMessage("general.errors.insufficient-rank", TextVariables.RANK, "ranks.visitor");
verify(player).playSound(user.getLocation(), Sound.BLOCK_METAL_HIT, 1F, 1F);
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.flags.clicklisteners.CommandRankClickListener#onClick(world.bentobox.bentobox.api.panels.Panel, world.bentobox.bentobox.api.user.User, org.bukkit.event.inventory.ClickType, int)}.
*/
@Test
public void testOnClickDifferentPanelName() {
when(panel.getName()).thenReturn("different");
assertTrue(crcl.onClick(panel, user, ClickType.LEFT, 0));
verify(inv, never()).setItem(eq(0), any());
verify(user).closeInventory();
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.flags.clicklisteners.CommandRankClickListener#onClick(world.bentobox.bentobox.api.panels.Panel, world.bentobox.bentobox.api.user.User, org.bukkit.event.inventory.ClickType, int)}.
*/
@Test
public void testOnClick() {
assertTrue(crcl.onClick(panel, user, ClickType.LEFT, 0));
verify(inv).setItem(eq(0), any());
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.flags.clicklisteners.CommandRankClickListener#onClick(world.bentobox.bentobox.api.panels.Panel, world.bentobox.bentobox.api.user.User, org.bukkit.event.inventory.ClickType, int)}.
*/
@Test
public void testOnClickTooManyCommands() {
Map<String, CompositeCommand> map = new HashMap<>();
for (int i = 0; i < 55; i++) {
CompositeCommand cc = mock(CompositeCommand.class);
when(cc.getWorld()).thenReturn(world);
when(cc.isConfigurableRankCommand()).thenReturn(true);
when(cc.getName()).thenReturn("test" + i);
when(cc.getSubCommands()).thenReturn(Collections.emptyMap());
map.put("test" + i, cc);
}
when(cm.getCommands()).thenReturn(map);
assertTrue(crcl.onClick(panel, user, ClickType.LEFT, 0));
verify(plugin).logError("Number of rank setting commands is too big for GUI");
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.flags.clicklisteners.CommandRankClickListener#getPanelItem(java.lang.String, world.bentobox.bentobox.api.user.User, org.bukkit.World)}.
*/
@Test
public void testGetPanelItem() {
assertTrue(crcl.onClick(panel, user, ClickType.LEFT, 0));
PanelItem pi = crcl.getPanelItem("test", user, world);
assertEquals(Material.MAP, pi.getItem().getType());
assertEquals("protection.panel.flag-item.description-layout", pi.getDescription().get(0));
assertEquals("protection.panel.flag-item.minimal-rankranks.member", pi.getDescription().get(1));
assertEquals("protection.panel.flag-item.allowed-rankranks.sub-owner", pi.getDescription().get(2));
assertEquals("protection.panel.flag-item.allowed-rankranks.owner", pi.getDescription().get(3));
assertTrue(pi.getClickHandler().isPresent());
assertEquals("test", pi.getName());
}
}

View File

@ -12,6 +12,7 @@ import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.event.block.BlockReceiveGameEvent;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@ -28,6 +29,7 @@ import world.bentobox.bentobox.util.Util;
* @author tastybento
*
*/
@Ignore("Has mocking issues with GameEvent")
@RunWith(PowerMockRunner.class)
@PrepareForTest( {BentoBox.class, Flags.class, Util.class, Bukkit.class} )
public class SculkSensorListenerTest extends AbstractCommonSetup {
@ -39,20 +41,21 @@ public class SculkSensorListenerTest extends AbstractCommonSetup {
/**
* @throws java.lang.Exception
*/
@Override
@Before
public void setUp() throws Exception {
super.setUp();
// Default is that everything is allowed
when(island.isAllowed(any(), any())).thenReturn(true);
// In world
when(iwm.inWorld(any(World.class))).thenReturn(true);
// Block
when(block.getType()).thenReturn(Material.SCULK_SENSOR);
when(block.getWorld()).thenReturn(world);
when(block.getLocation()).thenReturn(location);
// User
when(player.getWorld()).thenReturn(world);
when(player.getLocation()).thenReturn(location);
@ -71,7 +74,7 @@ public class SculkSensorListenerTest extends AbstractCommonSetup {
ssl.onSculkSensor(e);
assertTrue(e.isCancelled());
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.flags.protection.SculkSensorListener#onSculkSensor(org.bukkit.event.block.BlockReceiveGameEvent)}.
*/
@ -81,7 +84,7 @@ public class SculkSensorListenerTest extends AbstractCommonSetup {
ssl.onSculkSensor(e);
assertFalse(e.isCancelled());
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.flags.protection.SculkSensorListener#onSculkSensor(org.bukkit.event.block.BlockReceiveGameEvent)}.
*/
@ -92,7 +95,7 @@ public class SculkSensorListenerTest extends AbstractCommonSetup {
ssl.onSculkSensor(e);
assertFalse(e.isCancelled());
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.flags.protection.SculkSensorListener#onSculkSensor(org.bukkit.event.block.BlockReceiveGameEvent)}.
*/
@ -104,7 +107,7 @@ public class SculkSensorListenerTest extends AbstractCommonSetup {
ssl.onSculkSensor(e);
assertTrue(e.isCancelled());
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.flags.protection.SculkSensorListener#onSculkSensor(org.bukkit.event.block.BlockReceiveGameEvent)}.
*/
@ -115,7 +118,7 @@ public class SculkSensorListenerTest extends AbstractCommonSetup {
ssl.onSculkSensor(e);
assertFalse(e.isCancelled());
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.flags.protection.SculkSensorListener#onSculkSensor(org.bukkit.event.block.BlockReceiveGameEvent)}.
*/
@ -127,7 +130,7 @@ public class SculkSensorListenerTest extends AbstractCommonSetup {
ssl.onSculkSensor(e);
assertFalse(e.isCancelled());
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.flags.protection.SculkSensorListener#onSculkSensor(org.bukkit.event.block.BlockReceiveGameEvent)}.
*/
@ -139,7 +142,7 @@ public class SculkSensorListenerTest extends AbstractCommonSetup {
ssl.onSculkSensor(e);
assertFalse(e.isCancelled());
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.flags.protection.SculkSensorListener#onSculkSensor(org.bukkit.event.block.BlockReceiveGameEvent)}.
*/
@ -150,7 +153,7 @@ public class SculkSensorListenerTest extends AbstractCommonSetup {
ssl.onSculkSensor(e);
assertFalse(e.isCancelled());
}
/**
* Test method for {@link world.bentobox.bentobox.listeners.flags.protection.SculkSensorListener#onSculkSensor(org.bukkit.event.block.BlockReceiveGameEvent)}.
*/