1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-19 19:25:48 +00:00

Merge branch 'master' into performance/cobblestone

This commit is contained in:
TheBusyBiscuit 2021-01-11 13:58:21 +01:00 committed by GitHub
commit c92ba89d9a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
100 changed files with 2125 additions and 1804 deletions

View File

@ -6,6 +6,8 @@ on:
- 'src/**'
- '!src/main/resources/languages/**'
- 'pom.xml'
tags-ignore:
- 'RC.*'
jobs:
report:

View File

@ -2,7 +2,7 @@
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of contents**
- [Release Candidate 19 (TBD)](#release-candidate-19-tbd)
- [Release Candidate 19 (11 Jan 2021)](#release-candidate-19-11-jan-2021)
- [Release Candidate 18 (03 Dec 2020)](#release-candidate-18-03-dec-2020)
- [Release Candidate 17 (17 Oct 2020)](#release-candidate-17-17-oct-2020)
- [Release Candidate 16 (07 Sep 2020)](#release-candidate-16-07-sep-2020)
@ -24,18 +24,30 @@
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Release Candidate 19 (TBD)
## Release Candidate 20 (TBD)
#### Additions
#### Changes
#### Fixes
* Fixed elevator floor order
* Performance Improvements and Optimizations for Cobblestone/Stone/Basalt generators and mining androids
* Androids operating on a Cobblestone/Stone/Basalt generator now work faster
## Release Candidate 19 (11 Jan 2021)
#### Additions
* Added Bee Armor (1.15+ only)
* (API) Added AndroidFarmEvent
#### Changes
* Performance optimizations for Cargo networks
* Removed an old version of bStats
* CraftBukkit is officially no longer supported, Slimefun will now be disabled on old builds of CraftBukkit
* Removed the deprecated ItemManipulationAPI for BlockMenus
* Performance Improvements and Optimizations for Cobblestone/Stone/Basalt generators and mining androids
* Androids operating on a Cobblestone/Stone/Basalt generator now work faster
* Removed the "Written Book" variant of the Slimefun Guide
* The Elevator has an Inventory menu now
#### Fixes
* Fixed a couple of compatibility issues with ItemsAdder
@ -45,6 +57,8 @@
* Fixed #2647
* Fixed #2664
* Fixed #2655
* Fixed /sf timings --verbose not working correctly
* Fixed #2675
## Release Candidate 18 (03 Dec 2020)

15
pom.xml
View File

@ -336,7 +336,7 @@
<dependency>
<groupId>com.github.TheBusyBiscuit</groupId>
<artifactId>CS-CoreLib2</artifactId>
<version>0.27.4</version>
<version>0.29</version>
<scope>compile</scope>
</dependency>
<dependency>
@ -348,7 +348,7 @@
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-java</artifactId>
<version>3.11.09</version>
<version>3.11.10</version>
<scope>compile</scope>
<exclusions>
<exclusion>
@ -362,7 +362,7 @@
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<version>7.2.0</version>
<version>7.2.1</version>
<scope>provided</scope>
<exclusions>
<exclusion>
@ -380,7 +380,7 @@
<dependency>
<groupId>com.gmail.nossr50.mcMMO</groupId>
<artifactId>mcMMO</artifactId>
<version>2.1.170</version>
<version>2.1.171</version>
<scope>provided</scope>
<exclusions>
<exclusion>
@ -397,6 +397,13 @@
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-legacy</artifactId>
</exclusion>
<exclusion>
<!-- We do not want to use the wrong TextComponents by -->
<!-- accident. If we use adventure, then we will add -->
<!-- it ourselves. -->
<groupId>net.kyori</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>

View File

@ -0,0 +1,122 @@
package io.github.thebusybiscuit.slimefun4.api.events;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.bukkit.block.Block;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.implementation.items.androids.AndroidInstance;
import io.github.thebusybiscuit.slimefun4.implementation.items.androids.FarmerAndroid;
/**
* This {@link Event} is fired before a {@link FarmerAndroid} harvests a {@link Block}.
* If this {@link Event} is cancelled, the {@link Block} will not be harvested.
* <p>
* The {@link Event} will still be fired for non-harvestable blocks.
*
* @author TheBusyBiscuit
*
*/
public class AndroidFarmEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Block block;
private final AndroidInstance android;
private final boolean isAdvanced;
private ItemStack drop;
private boolean cancelled;
/**
* @param block
* The harvested {@link Block}
* @param android
* The {@link AndroidInstance} that triggered this {@link Event}
* @param isAdvanced
* Whether this is an advanced farming action
* @param drop
* The item to be dropped or null
*/
public AndroidFarmEvent(@Nonnull Block block, @Nonnull AndroidInstance android, boolean isAdvanced, @Nullable ItemStack drop) {
this.block = block;
this.android = android;
this.isAdvanced = isAdvanced;
this.drop = drop;
}
/**
* This method returns the mined {@link Block}
*
* @return the mined {@link Block}
*/
@Nonnull
public Block getBlock() {
return block;
}
/**
* This returns the harvested item or null.
*
* @return The harvested item or null
*/
@Nullable
public ItemStack getDrop() {
return drop;
}
/**
* Whether this was invoked via an advanced farming action
*
* @return Whether it is advanced
*/
public boolean isAdvanced() {
return isAdvanced;
}
/**
* This will set the {@link ItemStack} result.
*
* @param drop
* The result or null
*/
public void setDrop(@Nullable ItemStack drop) {
this.drop = drop;
}
/**
* This method returns the {@link AndroidInstance} who
* triggered this {@link Event}
*
* @return the involved {@link AndroidInstance}
*/
@Nonnull
public AndroidInstance getAndroid() {
return android;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
cancelled = cancel;
}
@Nonnull
public static HandlerList getHandlerList() {
return handlers;
}
@Nonnull
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
}

View File

@ -3,16 +3,16 @@ package io.github.thebusybiscuit.slimefun4.api.events;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.apache.commons.lang.Validate;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.ChestSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.CheatSheetSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunGuide;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
/**
* This {@link Event} is called whenever a {@link Player} clicks to unlock a {@link Research}.
@ -21,8 +21,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.guide.CheatSheetSlimefu
*
* @author uiytt
*
* @see ChestSlimefunGuide
* @see BookSlimefunGuide
* @see SurvivalSlimefunGuide
*
*/
public class PlayerPreResearchEvent extends Event implements Cancellable {

View File

@ -9,14 +9,14 @@ import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
/**
* This {@link Event} is called whenever a {@link Player} tries to open the Slimefun Guide book.
*
* @author Linox
*
* @see SlimefunGuideLayout
* @see SlimefunGuideMode
*/
public class SlimefunGuideOpenEvent extends Event implements Cancellable {
@ -24,10 +24,10 @@ public class SlimefunGuideOpenEvent extends Event implements Cancellable {
private final Player player;
private final ItemStack guide;
private SlimefunGuideLayout layout;
private SlimefunGuideMode layout;
private boolean cancelled;
public SlimefunGuideOpenEvent(@Nonnull Player p, @Nonnull ItemStack guide, @Nonnull SlimefunGuideLayout layout) {
public SlimefunGuideOpenEvent(@Nonnull Player p, @Nonnull ItemStack guide, @Nonnull SlimefunGuideMode layout) {
Validate.notNull(p, "The Player cannot be null");
Validate.notNull(guide, "Guide cannot be null");
Validate.notNull(layout, "Layout cannot be null");
@ -59,23 +59,23 @@ public class SlimefunGuideOpenEvent extends Event implements Cancellable {
}
/**
* This returns the {@link SlimefunGuideLayout} of the Slimefun Guide
* This returns the {@link SlimefunGuideMode} of the Slimefun Guide
* that {@link Player} tries to open.
*
* @return The {@link SlimefunGuideLayout}
* @return The {@link SlimefunGuideMode}
*/
@Nonnull
public SlimefunGuideLayout getGuideLayout() {
public SlimefunGuideMode getGuideLayout() {
return layout;
}
/**
* Changes the {@link SlimefunGuideLayout} that was tried to be opened with.
* Changes the {@link SlimefunGuideMode} that was tried to be opened with.
*
* @param layout
* The new {@link SlimefunGuideLayout}
* The new {@link SlimefunGuideMode}
*/
public void setGuideLayout(@Nonnull SlimefunGuideLayout layout) {
public void setGuideLayout(@Nonnull SlimefunGuideMode layout) {
Validate.notNull(layout, "You must specify a layout that is not-null!");
this.layout = layout;
}

View File

@ -23,7 +23,6 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.chat.ChatInput;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.api.events.WaypointCreateEvent;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.api.geo.ResourceManager;
@ -34,6 +33,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.gps.GPSTransmitte
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.Teleporter;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
@ -157,7 +157,7 @@ public class GPSNetwork {
if (sfi instanceof GPSTransmitter) {
int slot = inventory[index];
menu.addItem(slot, new CustomItem(SlimefunItems.GPS_TRANSMITTER, "&bGPS Transmitter", "&8\u21E8 &7World: &f" + l.getWorld().getName(), "&8\u21E8 &7X: &f" + l.getX(), "&8\u21E8 &7Y: &f" + l.getY(), "&8\u21E8 &7Z: &f" + l.getZ(), "", "&8\u21E8 &7Signal Strength: &f" + ((GPSTransmitter) sfi).getMultiplier(l.getBlockY()), "&8\u21E8 &7Ping: &f" + DoubleHandler.fixDouble(1000D / l.getY()) + "ms"));
menu.addItem(slot, new CustomItem(SlimefunItems.GPS_TRANSMITTER, "&bGPS Transmitter", "&8\u21E8 &7World: &f" + l.getWorld().getName(), "&8\u21E8 &7X: &f" + l.getX(), "&8\u21E8 &7Y: &f" + l.getY(), "&8\u21E8 &7Z: &f" + l.getZ(), "", "&8\u21E8 &7Signal Strength: &f" + ((GPSTransmitter) sfi).getMultiplier(l.getBlockY()), "&8\u21E8 &7Ping: &f" + NumberUtils.roundDecimalNumber(1000D / l.getY()) + "ms"));
menu.addMenuClickHandler(slot, ChestMenuUtils.getEmptyClickHandler());
index++;

View File

@ -20,11 +20,11 @@ import org.bukkit.potion.PotionEffectType;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
@ -64,7 +64,7 @@ public final class TeleportationManager {
int slot = teleporterInventory[index];
Location l = waypoint.getLocation();
double time = DoubleHandler.fixDouble(0.5 * getTeleportationTime(complexity, source, l));
double time = NumberUtils.reparseDouble(0.5 * getTeleportationTime(complexity, source, l));
String[] lore = { "", "&8\u21E8 &7" + SlimefunPlugin.getLocalization().getResourceString(p, "tooltips.world") + ": &f" + l.getWorld().getName(), "&8\u21E8 &7X: &f" + l.getX(), "&8\u21E8 &7Y: &f" + l.getY(), "&8\u21E8 &7Z: &f" + l.getZ(), "&8\u21E8 &7" + SlimefunPlugin.getLocalization().getMessage(p, "machines.TELEPORTER.gui.time") + ": &f" + time + "s", "", "&8\u21E8 &c" + SlimefunPlugin.getLocalization().getMessage(p, "machines.TELEPORTER.gui.tooltip") };

View File

@ -10,7 +10,6 @@ import org.apache.commons.lang.Validate;
import io.github.thebusybiscuit.cscorelib2.config.Config;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This class represents a Setting for a {@link SlimefunItem} that can be modified via
@ -152,19 +151,19 @@ public class ItemSetting<T> {
if (validateInput(newValue)) {
this.value = newValue;
} else {
Slimefun.getLogger().log(Level.WARNING, "Slimefun has found an invalid config setting in your Items.yml!");
Slimefun.getLogger().log(Level.WARNING, " at \"{0}.{1}\"", new Object[] { item.getId(), getKey() });
Slimefun.getLogger().log(Level.WARNING, "{0} is not a valid input!", configuredValue);
Slimefun.getLogger().log(Level.WARNING, getErrorMessage());
SlimefunPlugin.logger().log(Level.WARNING, "Slimefun has found an invalid config setting in your Items.yml!");
SlimefunPlugin.logger().log(Level.WARNING, " at \"{0}.{1}\"", new Object[] { item.getId(), getKey() });
SlimefunPlugin.logger().log(Level.WARNING, "{0} is not a valid input!", configuredValue);
SlimefunPlugin.logger().log(Level.WARNING, getErrorMessage());
}
} else {
this.value = defaultValue;
String found = configuredValue == null ? "null" : configuredValue.getClass().getSimpleName();
Slimefun.getLogger().log(Level.WARNING, "Slimefun has found an invalid config setting in your Items.yml!");
Slimefun.getLogger().log(Level.WARNING, "Please only use settings that are valid.");
Slimefun.getLogger().log(Level.WARNING, " at \"{0}.{1}\"", new Object[] { item.getId(), getKey() });
Slimefun.getLogger().log(Level.WARNING, "Expected \"{0}\" but found: \"{1}\"", new Object[] { defaultValue.getClass().getSimpleName(), found });
SlimefunPlugin.logger().log(Level.WARNING, "Slimefun has found an invalid config setting in your Items.yml!");
SlimefunPlugin.logger().log(Level.WARNING, "Please only use settings that are valid.");
SlimefunPlugin.logger().log(Level.WARNING, " at \"{0}.{1}\"", new Object[] { item.getId(), getKey() });
SlimefunPlugin.logger().log(Level.WARNING, "Expected \"{0}\" but found: \"{1}\"", new Object[] { defaultValue.getClass().getSimpleName(), found });
}
}

View File

@ -43,7 +43,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.armor.SlimefunArmorPiece;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* A class that can store a Player's {@link Research} progress for caching purposes.
@ -96,7 +95,7 @@ public final class PlayerProfile {
waypoints.add(new Waypoint(this, key, loc, waypointName));
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.WARNING, x, () -> "Could not load Waypoint \"" + key + "\" for Player \"" + p.getName() + '"');
SlimefunPlugin.logger().log(Level.WARNING, x, () -> "Could not load Waypoint \"" + key + "\" for Player \"" + p.getName() + '"');
}
}
}

View File

@ -14,6 +14,7 @@ import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nonnull;
import org.apache.commons.lang.Validate;
import org.bukkit.NamespacedKey;
import org.bukkit.Server;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@ -25,12 +26,13 @@ import io.github.thebusybiscuit.cscorelib2.config.Config;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideImplementation;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlock;
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.CheatSheetSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.ChestSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunGuide;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -71,12 +73,16 @@ public final class SlimefunRegistry {
private final Set<SlimefunItem> radioactive = new HashSet<>();
private final Set<ItemStack> barterDrops = new HashSet<>();
private NamespacedKey soulboundKey;
private NamespacedKey itemChargeKey;
private NamespacedKey guideKey;
private final KeyMap<GEOResource> geoResources = new KeyMap<>();
private final Map<UUID, PlayerProfile> profiles = new ConcurrentHashMap<>();
private final Map<String, BlockStorage> worlds = new ConcurrentHashMap<>();
private final Map<String, BlockInfoConfig> chunks = new HashMap<>();
private final Map<SlimefunGuideLayout, SlimefunGuideImplementation> layouts = new EnumMap<>(SlimefunGuideLayout.class);
private final Map<SlimefunGuideMode, SlimefunGuideImplementation> layouts = new EnumMap<>(SlimefunGuideMode.class);
private final Map<EntityType, Set<ItemStack>> mobDrops = new EnumMap<>(EntityType.class);
private final Map<String, BlockMenuPreset> blockMenuPresets = new HashMap<>();
@ -84,14 +90,17 @@ public final class SlimefunRegistry {
private final Map<Class<? extends ItemHandler>, Set<ItemHandler>> globalItemHandlers = new HashMap<>();
private final Map<String, SlimefunBlockHandler> blockHandlers = new HashMap<>();
public void load(@Nonnull Config cfg) {
public void load(@Nonnull SlimefunPlugin plugin, @Nonnull Config cfg) {
Validate.notNull(plugin, "The Plugin cannot be null!");
Validate.notNull(cfg, "The Config cannot be null!");
boolean showVanillaRecipes = cfg.getBoolean("guide.show-vanilla-recipes");
soulboundKey = new NamespacedKey(plugin, "soulbound");
itemChargeKey = new NamespacedKey(plugin, "item_charge");
guideKey = new NamespacedKey(plugin, "slimefun_guide_mode");
layouts.put(SlimefunGuideLayout.CHEST, new ChestSlimefunGuide(showVanillaRecipes));
layouts.put(SlimefunGuideLayout.CHEAT_SHEET, new CheatSheetSlimefunGuide());
layouts.put(SlimefunGuideLayout.BOOK, new BookSlimefunGuide());
boolean showVanillaRecipes = cfg.getBoolean("guide.show-vanilla-recipes");
layouts.put(SlimefunGuideMode.SURVIVAL_MODE, new SurvivalSlimefunGuide(showVanillaRecipes));
layouts.put(SlimefunGuideMode.CHEAT_MODE, new CheatSheetSlimefunGuide());
researchRanks.addAll(cfg.getStringList("research-ranks"));
@ -190,7 +199,7 @@ public final class SlimefunRegistry {
return multiblocks;
}
public SlimefunGuideImplementation getGuideLayout(SlimefunGuideLayout layout) {
public SlimefunGuideImplementation getGuideLayout(SlimefunGuideMode layout) {
return layouts.get(layout);
}
@ -262,4 +271,19 @@ public final class SlimefunRegistry {
return logDuplicateBlockEntries;
}
@Nonnull
public NamespacedKey getSoulboundDataKey() {
return soulboundKey;
}
@Nonnull
public NamespacedKey getItemChargeDataKey() {
return itemChargeKey;
}
@Nonnull
public NamespacedKey getGuideDataKey() {
return guideKey;
}
}

View File

@ -28,7 +28,6 @@ import net.md_5.bungee.api.ChatColor;
*/
final class RechargeableHelper {
private static final NamespacedKey CHARGE_KEY = new NamespacedKey(SlimefunPlugin.instance(), "item_charge");
private static final String LORE_PREFIX = ChatColors.color("&8\u21E8 &e\u26A1 &7");
private static final Pattern REGEX = Pattern.compile(ChatColors.color("(&c&o)?" + LORE_PREFIX) + "[0-9.]+ / [0-9.]+ J");
@ -38,7 +37,8 @@ final class RechargeableHelper {
BigDecimal decimal = BigDecimal.valueOf(charge).setScale(2, RoundingMode.HALF_UP);
float value = decimal.floatValue();
meta.getPersistentDataContainer().set(CHARGE_KEY, PersistentDataType.FLOAT, value);
NamespacedKey key = SlimefunPlugin.getRegistry().getItemChargeDataKey();
meta.getPersistentDataContainer().set(key, PersistentDataType.FLOAT, value);
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();
for (int i = 0; i < lore.size(); i++) {
@ -56,7 +56,8 @@ final class RechargeableHelper {
}
static float getCharge(@Nonnull ItemMeta meta) {
Float value = meta.getPersistentDataContainer().get(CHARGE_KEY, PersistentDataType.FLOAT);
NamespacedKey key = SlimefunPlugin.getRegistry().getItemChargeDataKey();
Float value = meta.getPersistentDataContainer().get(key, PersistentDataType.FLOAT);
// If persistent data is available, we just return this value
if (value != null) {

View File

@ -11,7 +11,7 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -45,12 +45,12 @@ public abstract class FlexCategory extends Category {
* @param profile
* The {@link PlayerProfile} of the {@link Player}
* @param layout
* The {@link SlimefunGuideLayout} in which this {@link FlexCategory} is viewed
* The {@link SlimefunGuideMode} in which this {@link FlexCategory} is viewed
*
* @return Whether to display this {@link FlexCategory}
*/
@ParametersAreNonnullByDefault
public abstract boolean isVisible(Player p, PlayerProfile profile, SlimefunGuideLayout layout);
public abstract boolean isVisible(Player p, PlayerProfile profile, SlimefunGuideMode layout);
/**
* This method is called when a {@link Player} opens this {@link FlexCategory}.
@ -62,9 +62,9 @@ public abstract class FlexCategory extends Category {
* @param profile
* The corresponding {@link PlayerProfile} for that {@link Player}
* @param layout
* The current {@link SlimefunGuideLayout}
* The current {@link SlimefunGuideMode}
*/
public abstract void open(Player p, PlayerProfile profile, SlimefunGuideLayout layout);
public abstract void open(Player p, PlayerProfile profile, SlimefunGuideMode layout);
@Override
public final boolean isHidden(@Nonnull Player p) {

View File

@ -14,6 +14,7 @@ import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.Category;
@ -76,8 +77,8 @@ public class LockedCategory extends Category {
}
@Override
public void register() {
super.register();
public void register(@Nonnull SlimefunAddon addon) {
super.register(addon);
List<NamespacedKey> namespacedKeys = new ArrayList<>();
@ -94,7 +95,7 @@ public class LockedCategory extends Category {
}
for (NamespacedKey key : namespacedKeys) {
Slimefun.getLogger().log(Level.INFO, "Parent \"{0}\" for Category \"{1}\" was not found, probably just disabled.", new Object[] { key, getKey() });
SlimefunPlugin.logger().log(Level.INFO, "Parent \"{0}\" for Category \"{1}\" was not found, probably just disabled.", new Object[] { key, getKey() });
}
}

View File

@ -6,7 +6,7 @@ import org.bukkit.entity.Player;
import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand;
import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class GuideCommand extends SubCommand {
@ -19,7 +19,7 @@ class GuideCommand extends SubCommand {
public void onExecute(CommandSender sender, String[] args) {
if (sender instanceof Player) {
if (sender.hasPermission("slimefun.command.guide")) {
SlimefunGuideLayout design = SlimefunGuide.getDefaultLayout();
SlimefunGuideMode design = SlimefunGuide.getDefaultLayout();
((Player) sender).getInventory().addItem(SlimefunGuide.getItem(design).clone());
} else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true);

View File

@ -1,12 +1,14 @@
package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand;
import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class OpenGuideCommand extends SubCommand {
@ -16,11 +18,11 @@ class OpenGuideCommand extends SubCommand {
}
@Override
@ParametersAreNonnullByDefault
public void onExecute(CommandSender sender, String[] args) {
if (sender instanceof Player) {
if (sender.hasPermission("slimefun.command.open_guide")) {
boolean book = SlimefunPlugin.getCfg().getBoolean("guide.default-view-book");
SlimefunGuide.openGuide((Player) sender, book ? SlimefunGuideLayout.BOOK : SlimefunGuideLayout.CHEST);
SlimefunGuide.openGuide((Player) sender, SlimefunGuideMode.SURVIVAL_MODE);
} else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true);
}

View File

@ -1,6 +1,12 @@
package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
@ -15,27 +21,76 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class TimingsCommand extends SubCommand {
private static final String FLAG_PREFIX = "--";
private final Set<String> flags = new HashSet<>(Arrays.asList("verbose"));
TimingsCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd, "timings", false);
}
@Override
protected String getDescription() {
return "commands.timings.description";
}
@Override
public void onExecute(CommandSender sender, String[] args) {
if (sender.hasPermission("slimefun.command.timings") || sender instanceof ConsoleCommandSender) {
sender.sendMessage("Please wait a second... The results are coming in!");
PerformanceInspector inspector = inspectorOf(sender);
if (hasInvalidFlags(sender, args)) {
return;
}
boolean verbose = hasFlag(args, "verbose");
if (verbose && sender instanceof Player) {
SlimefunPlugin.getLocalization().sendMessage(sender, "commands.timings.verbose-player", true);
return;
}
SlimefunPlugin.getLocalization().sendMessage(sender, "commands.timings.please-wait", true);
PerformanceInspector inspector = inspectorOf(sender, verbose);
SlimefunPlugin.getProfiler().requestSummary(inspector);
} else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true);
}
}
@ParametersAreNonnullByDefault
private boolean hasInvalidFlags(CommandSender sender, String[] args) {
boolean hasInvalidFlags = false;
// We start at 1 because args[0] will be "timings".
for (int i = 1; i < args.length; i++) {
String argument = args[i].toLowerCase(Locale.ROOT);
if (argument.startsWith(FLAG_PREFIX) && !flags.contains(argument.substring(2))) {
hasInvalidFlags = true;
SlimefunPlugin.getLocalization().sendMessage(sender, "commands.timings.unknown-flag", true, msg -> msg.replace("%flag%", argument));
}
}
return hasInvalidFlags;
}
@ParametersAreNonnullByDefault
private boolean hasFlag(String[] args, String flag) {
// We start at 1 because args[0] will be "timings".
for (int i = 1; i < args.length; i++) {
if (args[i].equalsIgnoreCase(FLAG_PREFIX + flag)) {
return true;
}
}
return false;
}
@Nonnull
private PerformanceInspector inspectorOf(@Nonnull CommandSender sender) {
private PerformanceInspector inspectorOf(@Nonnull CommandSender sender, boolean verbose) {
if (sender instanceof Player) {
return new PlayerPerformanceInspector((Player) sender);
} else {
return new ConsolePerformanceInspector(sender);
return new ConsolePerformanceInspector(sender, verbose);
}
}

View File

@ -2,6 +2,7 @@ package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
import java.util.Collection;
import javax.annotation.Nonnull;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@ -9,7 +10,6 @@ import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.plugin.Plugin;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.reflection.ReflectionUtils;
import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand;
import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
@ -22,14 +22,14 @@ class VersionsCommand extends SubCommand {
}
@Override
public void onExecute(CommandSender sender, String[] args) {
public void onExecute(@Nonnull CommandSender sender, @Nonnull String[] args) {
if (sender.hasPermission("slimefun.command.versions") || sender instanceof ConsoleCommandSender) {
// After all these years... Spigot still displays as "CraftBukkit"
// so we will just fix this inconsistency for them :)
String serverSoftware = PaperLib.isSpigot() && !PaperLib.isPaper() ? "Spigot" : Bukkit.getName();
sender.sendMessage(ChatColor.GRAY + "This Server uses the following setup of Slimefun:");
sender.sendMessage(ChatColors.color("&a" + serverSoftware + " &2" + ReflectionUtils.getVersion()));
sender.sendMessage(ChatColors.color("&a" + serverSoftware + " &2" + Bukkit.getVersion()));
sender.sendMessage(ChatColors.color("&aCS-CoreLib &2v" + SlimefunPlugin.getCSCoreLibVersion()));
sender.sendMessage(ChatColors.color("&aSlimefun &2v" + SlimefunPlugin.getVersion()));

View File

@ -3,14 +3,16 @@ package io.github.thebusybiscuit.slimefun4.core.guide;
import java.util.Optional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.ChestSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -22,36 +24,35 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
* @author TheBusyBiscuit
*
* @see SlimefunGuideImplementation
* @see ChestSlimefunGuide
* @see BookSlimefunGuide
* @see SurvivalSlimefunGuide
*
*/
public final class SlimefunGuide {
private SlimefunGuide() {}
public static ItemStack getItem(@Nonnull SlimefunGuideLayout design) {
@Nonnull
public static ItemStack getItem(@Nonnull SlimefunGuideMode design) {
return SlimefunPlugin.getRegistry().getGuideLayout(design).getItem();
}
public static void openCheatMenu(Player p) {
openMainMenuAsync(p, SlimefunGuideLayout.CHEAT_SHEET, 1);
public static void openCheatMenu(@Nonnull Player p) {
openMainMenuAsync(p, SlimefunGuideMode.CHEAT_MODE, 1);
}
public static void openGuide(Player p, ItemStack guide) {
if (SlimefunUtils.isItemSimilar(guide, getItem(SlimefunGuideLayout.CHEST), true)) {
openGuide(p, SlimefunGuideLayout.CHEST);
} else if (SlimefunUtils.isItemSimilar(guide, getItem(SlimefunGuideLayout.BOOK), true)) {
openGuide(p, SlimefunGuideLayout.BOOK);
} else if (SlimefunUtils.isItemSimilar(guide, getItem(SlimefunGuideLayout.CHEAT_SHEET), true)) {
openGuide(p, SlimefunGuideLayout.CHEAT_SHEET);
public static void openGuide(@Nonnull Player p, @Nullable ItemStack guide) {
if (getItem(SlimefunGuideMode.CHEAT_MODE).equals(guide)) {
openGuide(p, SlimefunGuideMode.CHEAT_MODE);
} else {
// When using /sf cheat or /sf open_guide, ItemStack is null.
openGuide(p, SlimefunGuideLayout.CHEST);
/*
* When using /sf cheat or /sf open_guide the ItemStack is null anyway,
* so we don't even need to check here at this point.
*/
openGuide(p, SlimefunGuideMode.SURVIVAL_MODE);
}
}
public static void openGuide(Player p, SlimefunGuideLayout layout) {
public static void openGuide(@Nonnull Player p, @Nonnull SlimefunGuideMode layout) {
if (!SlimefunPlugin.getWorldSettingsService().isWorldEnabled(p.getWorld())) {
return;
}
@ -67,51 +68,60 @@ public final class SlimefunGuide {
}
}
private static void openMainMenuAsync(Player player, SlimefunGuideLayout layout, int selectedPage) {
@ParametersAreNonnullByDefault
private static void openMainMenuAsync(Player player, SlimefunGuideMode layout, int selectedPage) {
if (!PlayerProfile.get(player, profile -> SlimefunPlugin.runSync(() -> openMainMenu(profile, layout, selectedPage)))) {
SlimefunPlugin.getLocalization().sendMessage(player, "messages.opening-guide");
}
}
public static void openMainMenu(PlayerProfile profile, SlimefunGuideLayout layout, int selectedPage) {
@ParametersAreNonnullByDefault
public static void openMainMenu(PlayerProfile profile, SlimefunGuideMode layout, int selectedPage) {
SlimefunPlugin.getRegistry().getGuideLayout(layout).openMainMenu(profile, selectedPage);
}
public static void openCategory(PlayerProfile profile, Category category, SlimefunGuideLayout layout, int selectedPage) {
if (category == null) {
return;
}
@ParametersAreNonnullByDefault
public static void openCategory(PlayerProfile profile, Category category, SlimefunGuideMode layout, int selectedPage) {
SlimefunPlugin.getRegistry().getGuideLayout(layout).openCategory(profile, category, selectedPage);
}
@ParametersAreNonnullByDefault
public static void openSearch(PlayerProfile profile, String input, boolean survival, boolean addToHistory) {
SlimefunGuideImplementation layout = SlimefunPlugin.getRegistry().getGuideLayout(SlimefunGuideLayout.CHEST);
SlimefunGuideImplementation layout = SlimefunPlugin.getRegistry().getGuideLayout(SlimefunGuideMode.SURVIVAL_MODE);
if (!survival) {
layout = SlimefunPlugin.getRegistry().getGuideLayout(SlimefunGuideLayout.CHEAT_SHEET);
layout = SlimefunPlugin.getRegistry().getGuideLayout(SlimefunGuideMode.CHEAT_MODE);
}
layout.openSearch(profile, input, addToHistory);
}
@ParametersAreNonnullByDefault
public static void displayItem(PlayerProfile profile, ItemStack item, boolean addToHistory) {
SlimefunPlugin.getRegistry().getGuideLayout(SlimefunGuideLayout.CHEST).displayItem(profile, item, 0, addToHistory);
SlimefunPlugin.getRegistry().getGuideLayout(SlimefunGuideMode.SURVIVAL_MODE).displayItem(profile, item, 0, addToHistory);
}
@ParametersAreNonnullByDefault
public static void displayItem(PlayerProfile profile, SlimefunItem item, boolean addToHistory) {
SlimefunPlugin.getRegistry().getGuideLayout(SlimefunGuideLayout.CHEST).displayItem(profile, item, addToHistory);
SlimefunPlugin.getRegistry().getGuideLayout(SlimefunGuideMode.SURVIVAL_MODE).displayItem(profile, item, addToHistory);
}
public static boolean isGuideItem(ItemStack item) {
return SlimefunUtils.isItemSimilar(item, getItem(SlimefunGuideLayout.CHEST), true) || SlimefunUtils.isItemSimilar(item, getItem(SlimefunGuideLayout.BOOK), true) || SlimefunUtils.isItemSimilar(item, getItem(SlimefunGuideLayout.CHEAT_SHEET), true);
}
public static SlimefunGuideLayout getDefaultLayout() {
if (SlimefunPlugin.getCfg().getBoolean("guide.default-view-book")) {
return SlimefunGuideLayout.BOOK;
public static boolean isGuideItem(@Nullable ItemStack item) {
if (item == null) {
return false;
} else {
return SlimefunGuideLayout.CHEST;
return SlimefunUtils.isItemSimilar(item, getItem(SlimefunGuideMode.SURVIVAL_MODE), true) || SlimefunUtils.isItemSimilar(item, getItem(SlimefunGuideMode.CHEAT_MODE), true);
}
}
/**
* Get the default layout for the Slimefun guide.
* Currently this is only {@link SlimefunGuideMode#SURVIVAL_MODE}.
*
* @return The default {@link SlimefunGuideLayout}.
*/
@Nonnull
public static SlimefunGuideMode getDefaultLayout() {
return SlimefunGuideMode.SURVIVAL_MODE;
}
}

View File

@ -11,8 +11,7 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.ChestSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunGuide;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -22,21 +21,20 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
*
* @author TheBusyBiscuit
*
* @see SlimefunGuideLayout
* @see ChestSlimefunGuide
* @see BookSlimefunGuide
* @see SlimefunGuideMode
* @see SurvivalSlimefunGuide
*
*/
public interface SlimefunGuideImplementation {
/**
* Every {@link SlimefunGuideImplementation} can be associated with a
* {@link SlimefunGuideLayout}.
* {@link SlimefunGuideMode}.
*
* @return The layout this {@link SlimefunGuideImplementation} represents
* @return The mode this {@link SlimefunGuideImplementation} represents
*/
@Nonnull
SlimefunGuideLayout getLayout();
SlimefunGuideMode getMode();
/**
* Returns the {@link ItemStack} representation for this {@link SlimefunGuideImplementation}.
@ -48,14 +46,6 @@ public interface SlimefunGuideImplementation {
@Nonnull
ItemStack getItem();
/**
* This method returns whether this {@link SlimefunGuideImplementation} is meant
* for Survival Mode.
*
* @return Whether this is a survival mode implementation
*/
boolean isSurvivalMode();
void openMainMenu(PlayerProfile profile, int page);
void openCategory(PlayerProfile profile, Category category, int page);

View File

@ -13,24 +13,17 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
* @see SlimefunGuideImplementation
*
*/
public enum SlimefunGuideLayout {
/**
* This design is a book representation of the {@link SlimefunGuide}
*/
BOOK,
public enum SlimefunGuideMode {
/**
* This design is the standard layout, it uses a {@link ChestMenu}
*/
CHEST,
SURVIVAL_MODE,
/**
* This is an admin-only design which creates a {@link SlimefunGuide} that allows
* you to spawn in any {@link SlimefunItem}
*/
CHEAT_SHEET;
public static final SlimefunGuideLayout[] valuesCache = values();
CHEAT_MODE;
}

View File

@ -4,6 +4,9 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
@ -13,35 +16,41 @@ import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
class GuideLayoutOption implements SlimefunGuideOption<SlimefunGuideLayout> {
class GuideModeOption implements SlimefunGuideOption<SlimefunGuideMode> {
@Nonnull
@Override
public SlimefunAddon getAddon() {
return SlimefunPlugin.instance();
}
@Nonnull
@Override
public NamespacedKey getKey() {
return new NamespacedKey(SlimefunPlugin.instance(), "guide_layout");
}
@Nonnull
@Override
public Optional<ItemStack> getDisplayItem(Player p, ItemStack guide) {
Optional<SlimefunGuideLayout> current = getSelectedOption(p, guide);
if (!p.hasPermission("slimefun.cheat.items")) {
// Only Players with the appropriate permission can access the cheat sheet
return Optional.empty();
}
Optional<SlimefunGuideMode> current = getSelectedOption(p, guide);
if (current.isPresent()) {
SlimefunGuideLayout layout = current.get();
SlimefunGuideMode layout = current.get();
ItemStack item = new ItemStack(Material.AIR);
if (layout == SlimefunGuideLayout.CHEST) {
if (layout == SlimefunGuideMode.SURVIVAL_MODE) {
item.setType(Material.CHEST);
} else if (layout == SlimefunGuideLayout.BOOK) {
item.setType(Material.BOOK);
} else {
item.setType(Material.COMMAND_BLOCK);
}
@ -50,12 +59,9 @@ class GuideLayoutOption implements SlimefunGuideOption<SlimefunGuideLayout> {
meta.setDisplayName(ChatColor.GRAY + "Slimefun Guide Design: " + ChatColor.YELLOW + ChatUtils.humanize(layout.name()));
List<String> lore = new ArrayList<>();
lore.add("");
lore.add((layout == SlimefunGuideLayout.CHEST ? ChatColor.GREEN : ChatColor.GRAY) + "Chest");
lore.add((layout == SlimefunGuideLayout.BOOK ? ChatColor.GREEN : ChatColor.GRAY) + "Book");
lore.add((layout == SlimefunGuideMode.SURVIVAL_MODE ? ChatColor.GREEN : ChatColor.GRAY) + "Chest");
if (p.hasPermission("slimefun.cheat.items")) {
lore.add((layout == SlimefunGuideLayout.CHEAT_SHEET ? ChatColor.GREEN : ChatColor.GRAY) + "Cheat Sheet");
}
lore.add((layout == SlimefunGuideMode.CHEAT_MODE ? ChatColor.GREEN : ChatColor.GRAY) + "Cheat Sheet");
lore.add("");
lore.add(ChatColor.GRAY + "\u21E8 " + ChatColor.YELLOW + "Click to change your layout");
@ -69,47 +75,44 @@ class GuideLayoutOption implements SlimefunGuideOption<SlimefunGuideLayout> {
}
@Override
public void onClick(Player p, ItemStack guide) {
Optional<SlimefunGuideLayout> current = getSelectedOption(p, guide);
public void onClick(@Nonnull Player p, @Nonnull ItemStack guide) {
Optional<SlimefunGuideMode> current = getSelectedOption(p, guide);
if (current.isPresent()) {
SlimefunGuideLayout next = getNextLayout(p, current.get());
SlimefunGuideMode next = getNextMode(p, current.get());
setSelectedOption(p, guide, next);
}
SlimefunGuideSettings.openSettings(p, guide);
}
private SlimefunGuideLayout getNextLayout(Player p, SlimefunGuideLayout layout) {
@Nonnull
private SlimefunGuideMode getNextMode(@Nonnull Player p, @Nonnull SlimefunGuideMode mode) {
if (p.hasPermission("slimefun.cheat.items")) {
if (layout == SlimefunGuideLayout.CHEST) {
return SlimefunGuideLayout.BOOK;
if (mode == SlimefunGuideMode.SURVIVAL_MODE) {
return SlimefunGuideMode.CHEAT_MODE;
} else {
return SlimefunGuideMode.SURVIVAL_MODE;
}
if (layout == SlimefunGuideLayout.BOOK) {
return SlimefunGuideLayout.CHEAT_SHEET;
}
return SlimefunGuideLayout.CHEST;
} else {
return layout == SlimefunGuideLayout.CHEST ? SlimefunGuideLayout.BOOK : SlimefunGuideLayout.CHEST;
return SlimefunGuideMode.SURVIVAL_MODE;
}
}
@Nonnull
@Override
public Optional<SlimefunGuideMode> getSelectedOption(@Nonnull Player p, @Nonnull ItemStack guide) {
if (SlimefunUtils.isItemSimilar(guide, SlimefunGuide.getItem(SlimefunGuideMode.CHEAT_MODE), true, false)) {
return Optional.of(SlimefunGuideMode.CHEAT_MODE);
} else {
return Optional.of(SlimefunGuideMode.SURVIVAL_MODE);
}
}
@Override
public Optional<SlimefunGuideLayout> getSelectedOption(Player p, ItemStack guide) {
for (SlimefunGuideLayout layout : SlimefunGuideLayout.valuesCache) {
if (SlimefunUtils.isItemSimilar(guide, SlimefunGuide.getItem(layout), true, false)) {
return Optional.of(layout);
}
}
return Optional.empty();
}
@Override
public void setSelectedOption(Player p, ItemStack guide, SlimefunGuideLayout value) {
@ParametersAreNonnullByDefault
public void setSelectedOption(Player p, ItemStack guide, SlimefunGuideMode value) {
guide.setItemMeta(SlimefunGuide.getItem(value).getItemMeta());
}
}
}

View File

@ -13,7 +13,7 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.core.services.localization.Language;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
@ -39,7 +39,7 @@ public final class SlimefunGuideSettings {
private static final List<SlimefunGuideOption<?>> options = new ArrayList<>();
static {
options.add(new GuideLayoutOption());
options.add(new GuideModeOption());
options.add(new FireworksOption());
options.add(new PlayerLanguageOption());
}
@ -65,7 +65,7 @@ public final class SlimefunGuideSettings {
}
private static void addHeader(Player p, ChestMenu menu, ItemStack guide) {
menu.addItem(0, new CustomItem(SlimefunGuide.getItem(SlimefunGuideLayout.CHEST), "&e\u21E6 " + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.title"), "", "&7" + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.guide")), (pl, slot, item, action) -> {
menu.addItem(0, new CustomItem(SlimefunGuide.getItem(SlimefunGuideMode.SURVIVAL_MODE), "&e\u21E6 " + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.title"), "", "&7" + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.guide")), (pl, slot, item, action) -> {
SlimefunGuide.openGuide(pl, guide);
return false;
});
@ -141,7 +141,7 @@ public final class SlimefunGuideSettings {
for (SlimefunGuideOption<?> option : options) {
if (option instanceof FireworksOption) {
FireworksOption fireworks = (FireworksOption) option;
return fireworks.getSelectedOption(p, SlimefunGuide.getItem(SlimefunGuideLayout.CHEST)).orElse(true);
return fireworks.getSelectedOption(p, SlimefunGuide.getItem(SlimefunGuideMode.SURVIVAL_MODE)).orElse(true);
}
}

View File

@ -31,10 +31,10 @@ import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.api.network.Network;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -365,7 +365,7 @@ abstract class AbstractItemNetwork extends Network {
ItemMeta im = stack.getItemMeta();
List<String> lore = new ArrayList<>();
lore.add("");
lore.add(ChatColors.color("&7Stored Items: &f" + DoubleHandler.getFancyDouble(item.getInt())));
lore.add(ChatColors.color("&7Stored Items: &f" + NumberUtils.getCompactDouble(item.getInt())));
if (stack.getMaxStackSize() > 1) {
int amount = item.getInt() > stack.getMaxStackSize() ? stack.getMaxStackSize() : item.getInt();

View File

@ -20,7 +20,6 @@ import io.github.thebusybiscuit.slimefun4.api.network.NetworkComponent;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.holograms.SimpleHologram;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link CargoNet} is a type of {@link Network} which deals with {@link ItemStack} transportation.
@ -250,7 +249,7 @@ public class CargoNet extends AbstractItemNetwork {
String str = BlockStorage.getLocationInfo(node).getString("frequency");
return str == null ? 0 : Integer.parseInt(str);
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Error occurred while parsing a Cargo Node Frequency (" + node.getWorld().getName() + " - " + node.getBlockX() + "," + node.getBlockY() + "," + +node.getBlockZ() + ")");
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Error occurred while parsing a Cargo Node Frequency (" + node.getWorld().getName() + " - " + node.getBlockX() + "," + node.getBlockY() + "," + +node.getBlockZ() + ")");
return 0;
}
}

View File

@ -22,9 +22,20 @@ import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
/**
* This is a helper class for the {@link CargoNet} which provides
* a free static utility methods to let the {@link CargoNet} interact with
* an {@link Inventory} or {@link BlockMenu}.
*
* @author TheBusyBiscuit
* @author Walshy
* @author DNx5
*
*/
final class CargoUtils {
/**
@ -32,6 +43,10 @@ final class CargoUtils {
*/
private static final int[] FILTER_SLOTS = { 19, 20, 21, 28, 29, 30, 37, 38, 39 };
/**
* This is a utility class and should not be instantiated.
* Therefore we just hide the public constructor.
*/
private CargoUtils() {}
/**
@ -51,10 +66,6 @@ final class CargoUtils {
Material type = block.getType();
if (SlimefunTag.SHULKER_BOXES.isTagged(type)) {
return true;
}
switch (type) {
case CHEST:
case TRAPPED_CHEST:
@ -68,10 +79,11 @@ final class CargoUtils {
case SMOKER:
return true;
default:
return false;
return SlimefunTag.SHULKER_BOXES.isTagged(type);
}
}
@Nonnull
static int[] getInputSlotRange(@Nonnull Inventory inv, @Nullable ItemStack item) {
if (inv instanceof FurnaceInventory) {
if (item != null && item.getType().isFuel()) {
@ -101,7 +113,8 @@ final class CargoUtils {
}
}
static int[] getOutputSlotRange(Inventory inv) {
@Nonnull
static int[] getOutputSlotRange(@Nonnull Inventory inv) {
if (inv instanceof FurnaceInventory) {
// Slot 2-3
return new int[] { 2, 3 };
@ -114,6 +127,7 @@ final class CargoUtils {
}
}
@Nullable
static ItemStack withdraw(AbstractItemNetwork network, Map<Location, Inventory> inventories, Block node, Block target, ItemStack template) {
DirtyChestMenu menu = getChestMenu(target);
@ -145,7 +159,7 @@ final class CargoUtils {
if (SlimefunUtils.isItemSimilar(is, wrapper, true) && matchesFilter(network, node, is)) {
if (is.getAmount() > template.getAmount()) {
is.setAmount(is.getAmount() - template.getAmount());
menu.replaceExistingItem(slot, is.clone());
menu.replaceExistingItem(slot, is);
return template;
} else {
menu.replaceExistingItem(slot, null);
@ -157,6 +171,7 @@ final class CargoUtils {
return null;
}
@Nullable
static ItemStack withdrawFromVanillaInventory(AbstractItemNetwork network, Block node, ItemStack template, Inventory inv) {
ItemStack[] contents = inv.getContents();
int[] range = getOutputSlotRange(inv);
@ -184,6 +199,7 @@ final class CargoUtils {
return null;
}
@Nullable
static ItemStackAndInteger withdraw(AbstractItemNetwork network, Map<Location, Inventory> inventories, Block node, Block target) {
DirtyChestMenu menu = getChestMenu(target);
@ -215,6 +231,7 @@ final class CargoUtils {
return null;
}
@Nullable
private static ItemStackAndInteger withdrawFromVanillaInventory(AbstractItemNetwork network, Block node, Inventory inv) {
ItemStack[] contents = inv.getContents();
int[] range = getOutputSlotRange(inv);
@ -233,6 +250,7 @@ final class CargoUtils {
return null;
}
@Nullable
static ItemStack insert(AbstractItemNetwork network, Map<Location, Inventory> inventories, Block node, Block target, ItemStack stack) {
if (!matchesFilter(network, node, stack)) {
return stack;
@ -273,7 +291,7 @@ final class CargoUtils {
int maxStackSize = itemInSlot.getType().getMaxStackSize();
int currentAmount = itemInSlot.getAmount();
if (SlimefunUtils.isItemSimilar(itemInSlot, wrapper, true, false) && currentAmount < maxStackSize) {
if (currentAmount < maxStackSize && SlimefunUtils.isItemSimilar(itemInSlot, wrapper, true, false)) {
int amount = currentAmount + stack.getAmount();
itemInSlot.setAmount(Math.min(amount, maxStackSize));
@ -291,6 +309,7 @@ final class CargoUtils {
return stack;
}
@Nullable
private static ItemStack insertIntoVanillaInventory(ItemStack stack, Inventory inv) {
ItemStack[] contents = inv.getContents();
int[] range = getInputSlotRange(inv, stack);
@ -309,7 +328,7 @@ final class CargoUtils {
} else {
int maxStackSize = itemInSlot.getType().getMaxStackSize();
if (SlimefunUtils.isItemSimilar(itemInSlot, wrapper, true, false) && itemInSlot.getAmount() < maxStackSize) {
if (itemInSlot.getAmount() < maxStackSize && SlimefunUtils.isItemSimilar(itemInSlot, wrapper, true, false)) {
int amount = itemInSlot.getAmount() + stack.getAmount();
if (amount > maxStackSize) {
@ -327,12 +346,13 @@ final class CargoUtils {
return stack;
}
@Nullable
static DirtyChestMenu getChestMenu(@Nonnull Block block) {
if (BlockStorage.hasInventory(block)) {
return BlockStorage.getInventory(block);
} else {
return BlockStorage.getUniversalInventory(block);
}
return BlockStorage.getUniversalInventory(block);
}
static boolean matchesFilter(@Nonnull AbstractItemNetwork network, @Nonnull Block node, @Nullable ItemStack item) {
@ -365,20 +385,12 @@ final class CargoUtils {
}
private static boolean isPotion(@Nullable ItemStack item) {
return item != null && (item.getType() == Material.POTION || item.getType() == Material.SPLASH_POTION || item.getType() == Material.LINGERING_POTION);
}
/**
* Get the whitelist/blacklist slots in a Cargo Input Node. If you wish to access the items
* in the cargo (without hardcoding the slots in case of change) then you can use this method.
*
* @deprecated Renamed to {@link #getFilteringSlots()}
*
* @return The slot indexes for the whitelist/blacklist section.
*/
@Deprecated
public static int[] getWhitelistBlacklistSlots() {
return FILTER_SLOTS;
if (item != null) {
Material type = item.getType();
return type == Material.POTION || type == Material.SPLASH_POTION || type == Material.LINGERING_POTION;
} else {
return false;
}
}
/**
@ -387,6 +399,7 @@ final class CargoUtils {
*
* @return The slots where the {@link ItemFilter} section for a cargo node sits
*/
@Nonnull
public static int[] getFilteringSlots() {
return FILTER_SLOTS;
}

View File

@ -15,7 +15,6 @@ import org.bukkit.entity.Player;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This Service is responsible for automatically saving {@link Player} and {@link Block}
@ -66,7 +65,7 @@ public class AutoSavingService {
}
if (players > 0) {
Slimefun.getLogger().log(Level.INFO, "Auto-saved all player data for {0} player(s)!", players);
SlimefunPlugin.logger().log(Level.INFO, "Auto-saved all player data for {0} player(s)!", players);
}
}
@ -89,7 +88,7 @@ public class AutoSavingService {
}
if (!worlds.isEmpty()) {
Slimefun.getLogger().log(Level.INFO, "Auto-saving block data... (Next auto-save: {0}m)", interval);
SlimefunPlugin.logger().log(Level.INFO, "Auto-saving block data... (Next auto-save: {0}m)", interval);
for (BlockStorage storage : worlds) {
storage.save();

View File

@ -20,7 +20,6 @@ import javax.annotation.Nonnull;
import org.apache.commons.lang.Validate;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This Service creates a Backup of your Slimefun world data on every server shutdown.
@ -43,7 +42,7 @@ public class BackupService implements Runnable {
try {
purgeBackups(backups);
} catch (IOException e) {
Slimefun.getLogger().log(Level.WARNING, "Could not delete an old backup", e);
SlimefunPlugin.logger().log(Level.WARNING, "Could not delete an old backup", e);
}
}
@ -56,12 +55,12 @@ public class BackupService implements Runnable {
createBackup(output);
}
Slimefun.getLogger().log(Level.INFO, "Backed up Slimefun data to: {0}", file.getName());
SlimefunPlugin.logger().log(Level.INFO, "Backed up Slimefun data to: {0}", file.getName());
} else {
Slimefun.getLogger().log(Level.WARNING, "Could not create backup-file: {0}", file.getName());
SlimefunPlugin.logger().log(Level.WARNING, "Could not create backup-file: {0}", file.getName());
}
} catch (IOException x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Error occurred while creating a backup for Slimefun " + SlimefunPlugin.getVersion());
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Error occurred while creating a backup for Slimefun " + SlimefunPlugin.getVersion());
}
}
}

View File

@ -19,8 +19,8 @@ import org.bukkit.persistence.PersistentDataHolder;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.plugin.Plugin;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link BlockDataService} is similar to the {@link CustomItemDataService},
@ -78,12 +78,12 @@ public class BlockDataService implements Keyed {
container.set(namespacedKey, PersistentDataType.STRING, value);
state.update();
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, "Please check if your Server Software is up to date!");
SlimefunPlugin.logger().log(Level.SEVERE, "Please check if your Server Software is up to date!");
String serverSoftware = PaperLib.isSpigot() && !PaperLib.isPaper() ? "Spigot" : Bukkit.getName();
Slimefun.getLogger().log(Level.SEVERE, () -> serverSoftware + " | " + Bukkit.getVersion() + " | " + Bukkit.getBukkitVersion());
SlimefunPlugin.logger().log(Level.SEVERE, () -> serverSoftware + " | " + Bukkit.getVersion() + " | " + Bukkit.getBukkitVersion());
Slimefun.getLogger().log(Level.SEVERE, "An Exception was thrown while trying to set Persistent Data for a Block", x);
SlimefunPlugin.logger().log(Level.SEVERE, "An Exception was thrown while trying to set Persistent Data for a Block", x);
}
}
}

View File

@ -30,6 +30,9 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
*/
public class CustomItemDataService implements Keyed {
/**
* This is the {@link NamespacedKey} used to store/read data.
*/
private final NamespacedKey namespacedKey;
/**

View File

@ -23,11 +23,10 @@ import org.bukkit.entity.Player;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.core.services.localization.Language;
import io.github.thebusybiscuit.slimefun4.core.services.localization.SlimefunLocalization;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
/**
* As the name suggests, this Service is responsible for Localization.
@ -78,7 +77,7 @@ public class LocalizationService extends SlimefunLocalization {
plugin.getLogger().log(Level.WARNING, "Could not recognize the given language: \"{0}\"", serverDefaultLanguage);
}
Slimefun.getLogger().log(Level.INFO, "Available languages: {0}", String.join(", ", languages.keySet()));
SlimefunPlugin.logger().log(Level.INFO, "Available languages: {0}", String.join(", ", languages.keySet()));
save();
} else {
translationsEnabled = false;
@ -178,7 +177,7 @@ public class LocalizationService extends SlimefunLocalization {
defaultLanguage.setCategoriesFile(streamConfigFile("categories_" + language + ".yml", null));
defaultLanguage.setRecipeTypesFile(streamConfigFile("recipes_" + language + ".yml", null));
Slimefun.getLogger().log(Level.INFO, "Loaded language \"{0}\"", language);
SlimefunPlugin.logger().log(Level.INFO, "Loaded language \"{0}\"", language);
getConfig().setValue(LANGUAGE_PATH, language);
// Loading in the defaults from our resources folder
@ -188,7 +187,7 @@ public class LocalizationService extends SlimefunLocalization {
FileConfiguration config = YamlConfiguration.loadConfiguration(reader);
getConfig().getConfiguration().setDefaults(config);
} catch (IOException e) {
Slimefun.getLogger().log(Level.SEVERE, e, () -> "Failed to load language file: \"" + path + "\"");
SlimefunPlugin.logger().log(Level.SEVERE, e, () -> "Failed to load language file: \"" + path + "\"");
}
save();
@ -245,13 +244,15 @@ public class LocalizationService extends SlimefunLocalization {
}
}
return Math.min(DoubleHandler.fixDouble(100.0 * (matches / (double) defaultKeys.size())), 100.0);
return Math.min(NumberUtils.reparseDouble(100.0 * (matches / (double) defaultKeys.size())), 100.0);
}
@Nonnull
private Set<String> getTotalKeys(@Nonnull Language lang) {
return getKeys(lang.getFiles());
}
@Nonnull
private Set<String> getKeys(FileConfiguration... files) {
Set<String> keys = new HashSet<>();
@ -278,7 +279,7 @@ public class LocalizationService extends SlimefunLocalization {
return config;
} catch (IOException e) {
Slimefun.getLogger().log(Level.SEVERE, e, () -> "Failed to load language file into memory: \"" + path + "\"");
SlimefunPlugin.logger().log(Level.SEVERE, e, () -> "Failed to load language file into memory: \"" + path + "\"");
return null;
}
}

View File

@ -20,14 +20,14 @@ import org.bukkit.plugin.Plugin;
import io.github.thebusybiscuit.cscorelib2.recipes.MinecraftRecipe;
import io.github.thebusybiscuit.cscorelib2.recipes.RecipeSnapshot;
import io.github.thebusybiscuit.slimefun4.implementation.guide.ChestSlimefunGuide;
import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunGuide;
/**
* This Service is responsible for accessing a {@link RecipeSnapshot}.
* This snapshot contains a compiled list of all recipes that could be found on the
* Server at the time the Service was loaded.
*
* This Service is primarily used by the {@link ChestSlimefunGuide}.
* This Service is primarily used by the {@link SurvivalSlimefunGuide}.
*
* @author TheBusyBiscuit
*

View File

@ -9,10 +9,10 @@ import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import kong.unirest.JsonNode;
import kong.unirest.json.JSONArray;
import kong.unirest.json.JSONObject;
import me.mrCookieSlime.Slimefun.api.Slimefun;
class ContributionsConnector extends GitHubConnector {
@ -84,7 +84,7 @@ class ContributionsConnector extends GitHubConnector {
if (response.isArray()) {
computeContributors(response.getArray());
} else {
Slimefun.getLogger().log(Level.WARNING, "Received an unusual answer from GitHub, possibly a timeout? ({0})", response);
SlimefunPlugin.logger().log(Level.WARNING, "Received an unusual answer from GitHub, possibly a timeout? ({0})", response);
}
}

View File

@ -181,10 +181,10 @@ public class Contributor {
public String getTexture() {
if (!headTexture.isComputed() || !headTexture.isPresent()) {
GitHubService github = SlimefunPlugin.getGitHubService();
String cached = github.getCachedTexture(githubUsername);
if (github != null) {
String cached = github.getCachedTexture(githubUsername);
return cached != null ? cached : HeadTexture.UNKNOWN.getTexture();
if (cached != null) {
return cached;
} else {
return HeadTexture.UNKNOWN.getTexture();
}

View File

@ -14,12 +14,12 @@ import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import kong.unirest.HttpResponse;
import kong.unirest.JsonNode;
import kong.unirest.Unirest;
import kong.unirest.UnirestException;
import kong.unirest.json.JSONException;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link GitHubConnector} is used to connect to the GitHub API service.
@ -100,7 +100,7 @@ abstract class GitHubConnector {
file = new File("plugins/Slimefun/cache/github/" + getFileName() + ".json");
if (github.isLoggingEnabled()) {
Slimefun.getLogger().log(Level.INFO, "Retrieving {0}.json from GitHub...", getFileName());
SlimefunPlugin.logger().log(Level.INFO, "Retrieving {0}.json from GitHub...", getFileName());
}
try {
@ -116,7 +116,7 @@ abstract class GitHubConnector {
writeCacheFile(response.getBody());
} else {
if (github.isLoggingEnabled()) {
Slimefun.getLogger().log(Level.WARNING, "Failed to fetch {0}: {1} - {2}", new Object[] { url, response.getStatus(), response.getBody() });
SlimefunPlugin.logger().log(Level.WARNING, "Failed to fetch {0}: {1} - {2}", new Object[] { url, response.getStatus(), response.getBody() });
}
// It has the cached file, let's just read that then
@ -130,7 +130,7 @@ abstract class GitHubConnector {
}
} catch (UnirestException e) {
if (github.isLoggingEnabled()) {
Slimefun.getLogger().log(Level.WARNING, "Could not connect to GitHub in time.", e);
SlimefunPlugin.logger().log(Level.WARNING, "Could not connect to GitHub in time.", e);
}
// It has the cached file, let's just read that then
@ -153,7 +153,7 @@ abstract class GitHubConnector {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {
return new JsonNode(reader.readLine());
} catch (IOException | JSONException e) {
Slimefun.getLogger().log(Level.WARNING, "Failed to read Github cache file: {0} - {1}: {2}", new Object[] { file.getName(), e.getClass().getSimpleName(), e.getMessage() });
SlimefunPlugin.logger().log(Level.WARNING, "Failed to read Github cache file: {0} - {1}: {2}", new Object[] { file.getName(), e.getClass().getSimpleName(), e.getMessage() });
return null;
}
}
@ -162,7 +162,7 @@ abstract class GitHubConnector {
try (FileOutputStream output = new FileOutputStream(file)) {
output.write(node.toString().getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
Slimefun.getLogger().log(Level.WARNING, "Failed to populate GitHub cache: {0} - {1}", new Object[] { e.getClass().getSimpleName(), e.getMessage() });
SlimefunPlugin.logger().log(Level.WARNING, "Failed to populate GitHub cache: {0} - {1}", new Object[] { e.getClass().getSimpleName(), e.getMessage() });
}
}
}

View File

@ -7,10 +7,10 @@ import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import kong.unirest.JsonNode;
import kong.unirest.json.JSONArray;
import kong.unirest.json.JSONObject;
import me.mrCookieSlime.Slimefun.api.Slimefun;
class GitHubIssuesConnector extends GitHubConnector {
@ -42,7 +42,7 @@ class GitHubIssuesConnector extends GitHubConnector {
callback.accept(issues, pullRequests);
} else {
Slimefun.getLogger().log(Level.WARNING, "Received an unusual answer from GitHub, possibly a timeout? ({0})", response);
SlimefunPlugin.logger().log(Level.WARNING, "Received an unusual answer from GitHub, possibly a timeout? ({0})", response);
}
}

View File

@ -16,7 +16,6 @@ import org.bukkit.Bukkit;
import io.github.thebusybiscuit.cscorelib2.players.MinecraftAccount;
import io.github.thebusybiscuit.cscorelib2.players.MinecraftAccount.TooManyRequestsException;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This {@link GitHubTask} represents a {@link Runnable} that is run every X minutes.
@ -101,8 +100,8 @@ class GitHubTask implements Runnable {
contributor.setTexture(null);
} catch (IOException x) {
// Too many requests
Slimefun.getLogger().log(Level.WARNING, "Attempted to connect to mojang.com, got this response: {0}: {1}", new Object[] { x.getClass().getSimpleName(), x.getMessage() });
Slimefun.getLogger().log(Level.WARNING, "This usually means mojang.com is temporarily down or started to rate-limit this connection, this is not an error message!");
SlimefunPlugin.logger().log(Level.WARNING, "Attempted to connect to mojang.com, got this response: {0}: {1}", new Object[] { x.getClass().getSimpleName(), x.getMessage() });
SlimefunPlugin.logger().log(Level.WARNING, "This usually means mojang.com is temporarily down or started to rate-limit this connection, this is not an error message!");
// Retry after 5 minutes if it was rate-limiting
if (x.getMessage().contains("429")) {
@ -111,7 +110,7 @@ class GitHubTask implements Runnable {
return -1;
} catch (TooManyRequestsException x) {
Slimefun.getLogger().log(Level.WARNING, "Received a rate-limit from mojang.com, retrying in 4 minutes");
SlimefunPlugin.logger().log(Level.WARNING, "Received a rate-limit from mojang.com, retrying in 4 minutes");
Bukkit.getScheduler().runTaskLaterAsynchronously(SlimefunPlugin.instance(), this::grabTextures, 4 * 60 * 20L);
return -1;

View File

@ -52,6 +52,8 @@ public class Translators {
// Translators - Hungarian
addTranslator("andris155", SupportedLanguage.HUNGARIAN, true);
addTranslator("KingDeadZ", SupportedLanguage.HUNGARIAN, true);
addTranslator("poma123", SupportedLanguage.HUNGARIAN, false);
// Translators - Vietnamese
addTranslator("HSGamer", SupportedLanguage.VIETNAMESE, false);
@ -180,8 +182,10 @@ public class Translators {
addTranslator("Sakanas", SupportedLanguage.PORTUGUESE_BRAZIL, true);
addTranslator("krazybeat", SupportedLanguage.PORTUGUESE_BRAZIL, true);
addTranslator("FaolanMalcadh", SupportedLanguage.PORTUGUESE_BRAZIL, true);
addTranslator("G4stavoM1ster", SupportedLanguage.PORTUGUESE_BRAZIL, true);
addTranslator("Gusstavo", SupportedLanguage.PORTUGUESE_BRAZIL, true);
addTranslator("Day-OS", SupportedLanguage.PORTUGUESE_BRAZIL, true);
addTranslator("ooicram", SupportedLanguage.PORTUGUESE_BRAZIL, true);
addTranslator("Sxigames", SupportedLanguage.PORTUGUESE_BRAZIL, true);
}
@ParametersAreNonnullByDefault

View File

@ -1,61 +0,0 @@
package io.github.thebusybiscuit.slimefun4.core.services.plugins;
import java.util.Optional;
import java.util.function.Function;
import javax.annotation.Nonnull;
import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.integrations.IntegrationsManager;
/**
* This Service holds all interactions and hooks with third-party {@link Plugin Plugins}
* that are not necessarily a dependency or a {@link SlimefunAddon}.
*
* Integration with these plugins happens inside Slimefun itself.
*
* @author TheBusyBiscuit
*
* @deprecated Renamed to {@link IntegrationsManager}
*
* @see SlimefunPlugin
*
*/
@Deprecated
public class ThirdPartyPluginService extends IntegrationsManager {
/**
* This gets overridden if ExoticGarden is loaded
*/
private Function<Block, Optional<ItemStack>> exoticGardenIntegration = b -> Optional.empty();
/**
* This initializes the {@link ThirdPartyPluginService}
*
* @param plugin
* Our instance of {@link SlimefunPlugin}
*/
public ThirdPartyPluginService(@Nonnull SlimefunPlugin plugin) {
super(plugin);
}
@Deprecated
public void loadExoticGarden(Plugin plugin, Function<Block, Optional<ItemStack>> method) {
// TODO: Move this method to IntegrationsManager and think of a better way to handle this
// For next RC!
if (plugin.getName().equals("ExoticGarden")) {
exoticGardenIntegration = method;
}
}
@Deprecated
public Optional<ItemStack> harvestExoticGardenPlant(Block block) {
return exoticGardenIntegration.apply(block);
}
}

View File

@ -1,4 +0,0 @@
/**
* This package contains all hooks to external plugins
*/
package io.github.thebusybiscuit.slimefun4.core.services.plugins;

View File

@ -36,6 +36,6 @@ public interface PerformanceInspector {
*
* @return Whether to send the full {@link PerformanceSummary} or a trimmed version
*/
boolean hasFullView();
boolean isVerbose();
}

View File

@ -152,7 +152,7 @@ class PerformanceSummary {
builder.append(ChatColor.YELLOW);
for (Map.Entry<String, Long> entry : results) {
if (!inspector.hasFullView() || (shownEntries < MAX_ITEMS && (shownEntries < MIN_ITEMS || entry.getValue() > VISIBILITY_THRESHOLD))) {
if (inspector.isVerbose() || (shownEntries < MAX_ITEMS && (shownEntries < MIN_ITEMS || entry.getValue() > VISIBILITY_THRESHOLD))) {
builder.append("\n ");
builder.append(ChatColor.stripColor(formatter.apply(entry)));
shownEntries++;

View File

@ -26,7 +26,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.TickerTask;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link SlimefunProfiler} works closely to the {@link TickerTask} and is
@ -192,7 +191,7 @@ public class SlimefunProfiler {
return;
}
} catch (InterruptedException e) {
Slimefun.getLogger().log(Level.SEVERE, "A Profiler Thread was interrupted", e);
SlimefunPlugin.logger().log(Level.SEVERE, "A Profiler Thread was interrupted", e);
Thread.currentThread().interrupt();
}
}

View File

@ -23,16 +23,24 @@ public class ConsolePerformanceInspector implements PerformanceInspector {
*/
private final CommandSender console;
/**
* Whether a summary will be verbose or trimmed of.
*/
private final boolean verbose;
/**
* This creates a new {@link ConsolePerformanceInspector} for the given {@link CommandSender}.
*
* @param console
* The {@link CommandSender}, preferabbly a {@link ConsoleCommandSender}
* @param verbose
* Whether the summary will be verbose or not
*/
public ConsolePerformanceInspector(@Nonnull CommandSender console) {
public ConsolePerformanceInspector(@Nonnull CommandSender console, boolean verbose) {
Validate.notNull(console, "CommandSender cannot be null");
this.console = console;
this.verbose = verbose;
}
@Override
@ -42,8 +50,8 @@ public class ConsolePerformanceInspector implements PerformanceInspector {
}
@Override
public boolean hasFullView() {
return false;
public boolean isVerbose() {
return verbose;
}
@Override

View File

@ -50,7 +50,7 @@ public class PlayerPerformanceInspector implements PerformanceInspector {
}
@Override
public boolean hasFullView() {
public boolean isVerbose() {
return false;
}

View File

@ -8,6 +8,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
@ -49,7 +50,6 @@ import io.github.thebusybiscuit.slimefun4.core.services.PerWorldSettingsService;
import io.github.thebusybiscuit.slimefun4.core.services.PermissionsService;
import io.github.thebusybiscuit.slimefun4.core.services.UpdaterService;
import io.github.thebusybiscuit.slimefun4.core.services.github.GitHubService;
import io.github.thebusybiscuit.slimefun4.core.services.plugins.ThirdPartyPluginService;
import io.github.thebusybiscuit.slimefun4.core.services.profiler.SlimefunProfiler;
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientAltar;
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientPedestal;
@ -150,13 +150,12 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
private final PerWorldSettingsService worldSettingsService = new PerWorldSettingsService(this);
private final MinecraftRecipeService recipeService = new MinecraftRecipeService(this);
private final IntegrationsManager integrations = new ThirdPartyPluginService(this);
private final IntegrationsManager integrations = new IntegrationsManager(this);
private final SlimefunProfiler profiler = new SlimefunProfiler();
private LocalizationService local;
private LocalizationService local;
private GPSNetwork gpsNetwork;
private NetworkManager networkManager;
private ProtectionManager protections;
// Important config files for Slimefun
private final Config config = new Config(this);
@ -203,7 +202,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
if (minecraftVersion == MinecraftVersion.UNIT_TEST) {
// We handle Unit Tests seperately.
setInstance(this);
getLogger().log(Level.INFO, "This is a UNIT TEST Environment.");
onUnitTestStart();
} else if (isVersionUnsupported()) {
// We wanna ensure that the Server uses a compatible version of Minecraft.
@ -227,6 +225,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
getLogger().log(Level.INFO, "Please download and install CS-CoreLib manually:");
getLogger().log(Level.INFO, "https://thebusybiscuit.github.io/builds/TheBusyBiscuit/CS-CoreLib/master/");
// Send a message upon doing /slimefun
getCommand("slimefun").setExecutor((sender, cmd, label, args) -> {
sender.sendMessage("You have forgotten to install CS-CoreLib! Slimefun is disabled.");
sender.sendMessage("https://thebusybiscuit.github.io/builds/TheBusyBiscuit/CS-CoreLib/master/");
@ -243,7 +242,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
gpsNetwork = new GPSNetwork();
networkManager = new NetworkManager(200);
command.register();
registry.load(config);
registry.load(this, config);
loadTags();
}
@ -270,7 +269,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
// Creating all necessary Folders
getLogger().log(Level.INFO, "Creating directories...");
createDirectories();
registry.load(config);
registry.load(this, config);
// Set up localization
getLogger().log(Level.INFO, "Loading language files...");
@ -320,7 +319,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
// Initiating various Stuff and all items with a slight delay (0ms after the Server finished loading)
runSync(new SlimefunStartupTask(this, () -> {
protections = new ProtectionManager(getServer());
textureService.register(registry.getAllSlimefunItems(), true);
permissionsService.register(registry.getAllSlimefunItems(), true);
@ -333,8 +331,12 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
}), 0);
// Setting up the command /sf and all subcommands
command.register();
// Setting up our commands
try {
command.register();
} catch (Exception | LinkageError x) {
getLogger().log(Level.SEVERE, "An Exception occurred while registering the /slimefun command", x);
}
// Armor Update Task
if (config.getBoolean("options.enable-armor-effects")) {
@ -342,9 +344,11 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
getServer().getScheduler().runTaskTimerAsynchronously(this, new ArmorTask(radioactiveFire), 0L, config.getInt("options.armor-update-interval") * 20L);
}
// Starting our tasks
autoSavingService.start(this, config.getInt("options.auto-save-delay-in-minutes"));
ticker.start(this);
// Loading integrations
getLogger().log(Level.INFO, "Loading Third-Party plugin integrations...");
integrations.start();
gitHubService.start(this);
@ -353,6 +357,16 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
getLogger().log(Level.INFO, "Slimefun has finished loading in {0}", getStartupTime(timestamp));
}
@Override
public JavaPlugin getJavaPlugin() {
return this;
}
@Override
public String getBugTrackerURL() {
return "https://github.com/Slimefun/Slimefun4/issues";
}
/**
* This method gets called when the {@link Plugin} gets disabled.
* Most often it is called when the {@link Server} is shutting down or reloading.
@ -390,6 +404,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
}
}
// Save all "universal" inventories (ender chests for example)
for (UniversalBlockMenu menu : registry.getUniversalInventories().values()) {
menu.save();
}
@ -428,6 +443,14 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
instance = pluginInstance;
}
/**
* This returns the time it took to load Slimefun (given a starting point).
*
* @param timestamp
* The time at which we started to load Slimefun.
*
* @return The total time it took to load Slimefun (in ms or s)
*/
@Nonnull
private String getStartupTime(long timestamp) {
long ms = (System.nanoTime() - timestamp) / 1000000;
@ -519,6 +542,18 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
}
}
/**
* This private method gives us a {@link Collection} of every {@link MinecraftVersion}
* that Slimefun is compatible with (as a {@link String} representation).
* <p>
* Example:
*
* <pre>
* { 1.14.x, 1.15.x, 1.16.x }
* </pre>
*
* @return A {@link Collection} of all compatible minecraft versions as strings
*/
@Nonnull
private Collection<String> getSupportedVersions() {
List<String> list = new ArrayList<>();
@ -532,6 +567,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
return list;
}
/**
* This method creates all necessary directories (and sub directories) for Slimefun.
*/
private void createDirectories() {
String[] storageFolders = { "Players", "blocks", "stored-blocks", "stored-inventories", "stored-chunks", "universal-inventories", "waypoints", "block-backups" };
String[] pluginFolders = { "scripts", "error-reports", "cache/github", "world-settings" };
@ -627,6 +665,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
new PlayerProfileListener(this);
}
/**
* This (re)loads every {@link SlimefunTag}.
*/
private void loadTags() {
for (SlimefunTag tag : SlimefunTag.valuesCache) {
try {
@ -640,6 +681,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
}
}
/**
* This loads all of our items.
*/
private void loadItems() {
try {
SlimefunItemSetup.setup(this);
@ -648,6 +692,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
}
}
/**
* This loads our researches.
*/
private void loadResearches() {
try {
ResearchSetup.setupResearches();
@ -656,6 +703,19 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
}
}
/**
* This private static method allows us to throw a proper {@link Exception}
* whenever someone tries to access a static method while the instance is null.
* This happens when the method is invoked before {@link #onEnable()} or after {@link #onDisable()}.
* <p>
* Use it whenever a null check is needed to avoid a non-descriptive {@link NullPointerException}.
*/
private static void validateInstance() {
if (instance == null) {
throw new IllegalStateException("Cannot invoke static method, Slimefun instance is null.");
}
}
/**
* This returns the global instance of {@link SlimefunPlugin}.
* This may return null if the {@link Plugin} was disabled.
@ -667,24 +727,17 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
return instance;
}
public static Config getCfg() {
return instance.config;
}
public static Config getResearchCfg() {
return instance.researches;
}
public static Config getItemCfg() {
return instance.items;
}
public static GPSNetwork getGPSNetwork() {
return instance.gpsNetwork;
}
public static TickerTask getTickerTask() {
return instance.ticker;
/**
* This returns the {@link Logger} instance that Slimefun uses.
* <p>
* <strong>Any {@link SlimefunAddon} should use their own {@link Logger} instance!</strong>
*
* @return Our {@link Logger} instance
*/
@Nonnull
public static Logger logger() {
validateInstance();
return instance.getLogger();
}
/**
@ -692,59 +745,89 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
*
* @return The currently installed version of Slimefun
*/
@Nonnull
public static String getVersion() {
validateInstance();
return instance.getDescription().getVersion();
}
@Nonnull
public static Config getCfg() {
validateInstance();
return instance.config;
}
@Nonnull
public static Config getResearchCfg() {
validateInstance();
return instance.researches;
}
@Nonnull
public static Config getItemCfg() {
validateInstance();
return instance.items;
}
@Nonnull
public static GPSNetwork getGPSNetwork() {
validateInstance();
return instance.gpsNetwork;
}
@Nonnull
public static TickerTask getTickerTask() {
validateInstance();
return instance.ticker;
}
/**
* This returns the {@link LocalizationService} of Slimefun.
*
* @return The {@link LocalizationService} of Slimefun
*/
@Nonnull
public static LocalizationService getLocalization() {
validateInstance();
return instance.local;
}
public static ProtectionManager getProtectionManager() {
return instance.protections;
}
@Nonnull
public static MinecraftRecipeService getMinecraftRecipeService() {
validateInstance();
return instance.recipeService;
}
@Nonnull
public static CustomItemDataService getItemDataService() {
validateInstance();
return instance.itemDataService;
}
@Nonnull
public static CustomTextureService getItemTextureService() {
validateInstance();
return instance.textureService;
}
@Nonnull
public static PermissionsService getPermissionsService() {
validateInstance();
return instance.permissionsService;
}
@Nonnull
public static BlockDataService getBlockDataService() {
validateInstance();
return instance.blockDataService;
}
@Nonnull
public static PerWorldSettingsService getWorldSettingsService() {
validateInstance();
return instance.worldSettingsService;
}
/**
* This method has been renamed.
*
* @deprecated Please use {@link #getIntegrations()} instead.
*
* @return the {@link ThirdPartyPluginService}
*/
@Deprecated
public static ThirdPartyPluginService getThirdPartySupportService() {
return (ThirdPartyPluginService) instance.integrations;
}
/**
* This returns our instance of {@link IntegrationsManager}.
* This is responsible for managing any integrations with third party {@link Plugin plugins}.
@ -753,16 +836,30 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
*/
@Nonnull
public static IntegrationsManager getIntegrations() {
validateInstance();
return instance.integrations;
}
/**
* This returns out instance of the {@link ProtectionManager}.
* This bridge is used to hook into any third-party protection {@link Plugin}.
*
* @return Our instanceof of the {@link ProtectionManager}
*/
@Nonnull
public static ProtectionManager getProtectionManager() {
return getIntegrations().getProtectionManager();
}
/**
* This method returns the {@link UpdaterService} of Slimefun.
* It is used to handle automatic updates.
*
* @return The {@link UpdaterService} for Slimefun
*/
@Nonnull
public static UpdaterService getUpdater() {
validateInstance();
return instance.updaterService;
}
@ -772,7 +869,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
*
* @return The {@link MetricsService} for Slimefun
*/
@Nonnull
public static MetricsService getMetricsService() {
validateInstance();
return instance.metricsService;
}
@ -782,30 +881,105 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
*
* @return The {@link GitHubService} for Slimefun
*/
@Nonnull
public static GitHubService getGitHubService() {
validateInstance();
return instance.gitHubService;
}
public static SlimefunRegistry getRegistry() {
return instance.registry;
}
/**
* This returns our {@link NetworkManager} which is responsible
* for handling the Cargo and Energy networks.
*
* @return Our {@link NetworkManager} instance
*/
@Nonnull
public static NetworkManager getNetworkManager() {
validateInstance();
return instance.networkManager;
}
@Nonnull
public static SlimefunRegistry getRegistry() {
validateInstance();
return instance.registry;
}
@Nonnull
public static GrapplingHookListener getGrapplingHookListener() {
validateInstance();
return instance.grapplingHookListener;
}
@Nonnull
public static BackpackListener getBackpackListener() {
validateInstance();
return instance.backpackListener;
}
@Nonnull
public static SlimefunBowListener getBowListener() {
validateInstance();
return instance.bowListener;
}
/**
* The {@link Command} that was added by Slimefun.
*
* @return Slimefun's command
*/
@Nonnull
public static SlimefunCommand getCommand() {
validateInstance();
return instance.command;
}
/**
* This returns our instance of the {@link SlimefunProfiler}, a tool that is used
* to analyse performance and lag.
*
* @return The {@link SlimefunProfiler}
*/
@Nonnull
public static SlimefunProfiler getProfiler() {
validateInstance();
return instance.profiler;
}
/**
* This returns the currently installed version of Minecraft.
*
* @return The current version of Minecraft
*/
@Nonnull
public static MinecraftVersion getMinecraftVersion() {
validateInstance();
return instance.minecraftVersion;
}
/**
* This method returns whether this version of Slimefun was newly installed.
* It will return true if this {@link Server} uses Slimefun for the very first time.
*
* @return Whether this is a new installation of Slimefun
*/
public static boolean isNewlyInstalled() {
validateInstance();
return instance.isNewlyInstalled;
}
@Nonnull
public static String getCSCoreLibVersion() {
validateInstance();
Plugin cscorelib = instance.getServer().getPluginManager().getPlugin("CS-CoreLib");
if (cscorelib == null) {
throw new IllegalStateException("CS-CoreLib is not installed.");
} else {
return cscorelib.getDescription().getVersion();
}
}
/**
* This method returns a {@link Set} of every {@link Plugin} that lists Slimefun
* as a required or optional dependency.
@ -816,6 +990,8 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
*/
@Nonnull
public static Set<Plugin> getInstalledAddons() {
validateInstance();
String pluginName = instance.getName();
// @formatter:off
@ -827,65 +1003,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
// @formatter:on
}
/**
* The {@link Command} that was added by Slimefun.
*
* @return Slimefun's command
*/
public static SlimefunCommand getCommand() {
return instance.command;
}
/**
* This returns our instance of the {@link SlimefunProfiler}, a tool that is used
* to analyse performance and lag.
*
* @return The {@link SlimefunProfiler}
*/
public static SlimefunProfiler getProfiler() {
return instance.profiler;
}
/**
* This returns the currently installed version of Minecraft.
*
* @return The current version of Minecraft
*/
public static MinecraftVersion getMinecraftVersion() {
return instance.minecraftVersion;
}
/**
* This method returns whether this version of Slimefun was newly installed.
* It will return true if this {@link Server} uses Slimefun for the very first time.
*
* @return Whether this is a new installation of Slimefun
*/
public static boolean isNewlyInstalled() {
return instance.isNewlyInstalled;
}
@Nonnull
public static String getCSCoreLibVersion() {
Plugin cscorelib = instance.getServer().getPluginManager().getPlugin("CS-CoreLib");
if (cscorelib == null) {
throw new IllegalStateException("CS-CoreLib is not installed.");
} else {
return cscorelib.getDescription().getVersion();
}
}
@Override
public JavaPlugin getJavaPlugin() {
return this;
}
@Override
public String getBugTrackerURL() {
return "https://github.com/Slimefun/Slimefun4/issues";
}
/**
* This method schedules a delayed synchronous task for Slimefun.
* <strong>For Slimefun only, not for addons.</strong>
@ -945,4 +1062,4 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
return instance.getServer().getScheduler().runTask(instance, runnable);
}
}
}

View File

@ -1,253 +0,0 @@
package io.github.thebusybiscuit.slimefun4.implementation.guide;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import org.bukkit.ChatColor;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.chat.ChatInput;
import io.github.thebusybiscuit.cscorelib2.chat.json.ChatComponent;
import io.github.thebusybiscuit.cscorelib2.chat.json.ClickEvent;
import io.github.thebusybiscuit.cscorelib2.chat.json.CustomBookInterface;
import io.github.thebusybiscuit.cscorelib2.chat.json.HoverEvent;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory;
import io.github.thebusybiscuit.slimefun4.core.categories.LockedCategory;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideImplementation;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.SlimefunGuideItem;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link BookSlimefunGuide} is a {@link SlimefunGuideImplementation} which
* uses a {@link CustomBookInterface} to display the contents of the {@link SlimefunGuide}.
* {@link Player Players} have the option to choose this Written Book layout over the
* standard {@link Inventory} variant.
*
* @author TheBusyBiscuit
*
* @see SlimefunGuide
* @see SlimefunGuideImplementation
* @see ChestSlimefunGuide
* @see CheatSheetSlimefunGuide
*
*/
public class BookSlimefunGuide implements SlimefunGuideImplementation {
private final NamespacedKey guideSearch = new NamespacedKey(SlimefunPlugin.instance(), "search");
private final ItemStack item;
public BookSlimefunGuide() {
item = new SlimefunGuideItem(this, "&aSlimefun Guide &7(Book GUI)");
}
@Override
public SlimefunGuideLayout getLayout() {
return SlimefunGuideLayout.BOOK;
}
@Override
public boolean isSurvivalMode() {
return true;
}
@Override
public ItemStack getItem() {
return item;
}
private void openBook(Player p, PlayerProfile profile, List<ChatComponent> lines, boolean backButton) {
CustomBookInterface book = new CustomBookInterface(SlimefunPlugin.instance());
book.setTitle(SlimefunPlugin.getLocalization().getMessage(p, "guide.title.main"));
for (int i = 0; i < lines.size(); i = i + 10) {
ChatComponent page = new ChatComponent("");
ChatComponent header = new ChatComponent(ChatColors.color("&b&l- " + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.main") + " -\n\n"));
header.setHoverEvent(new HoverEvent(ChestMenuUtils.getSearchButton(p)));
header.setClickEvent(new ClickEvent(guideSearch, player -> SlimefunPlugin.runSync(() -> {
SlimefunPlugin.getLocalization().sendMessage(player, "guide.search.message");
ChatInput.waitForPlayer(SlimefunPlugin.instance(), player, msg -> SlimefunGuide.openSearch(profile, msg, true, true));
}, 1)));
page.append(header);
for (int j = i; j < lines.size() && j < i + 10; j++) {
page.append(lines.get(j));
}
page.append(new ChatComponent("\n"));
if (backButton) {
ChatComponent button = new ChatComponent(ChatColor.DARK_BLUE + "\u21E6 " + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.title"));
button.setHoverEvent(new HoverEvent(ChatColor.DARK_BLUE + "\u21E6 " + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.title"), "", ChatColor.GRAY + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.guide")));
button.setClickEvent(new ClickEvent(new NamespacedKey(SlimefunPlugin.instance(), "slimefun_guide"), pl -> openMainMenu(profile, 1)));
page.append(button);
}
book.addPage(page);
}
book.open(p);
}
@Override
public void openMainMenu(PlayerProfile profile, int page) {
Player p = profile.getPlayer();
if (p == null) {
return;
}
List<ChatComponent> lines = new LinkedList<>();
int tier = 0;
for (Category category : SlimefunPlugin.getRegistry().getCategories()) {
if (!category.isHidden(p) && (!(category instanceof FlexCategory) || ((FlexCategory) category).isVisible(p, profile, getLayout()))) {
if (tier < category.getTier()) {
tier = category.getTier();
if (tier > 1) {
for (int i = 0; i < 10 && lines.size() % 10 != 0; i++) {
lines.add(new ChatComponent("\n"));
}
}
lines.add(new ChatComponent(ChatColor.DARK_GRAY + "\u21E8" + ChatColor.DARK_BLUE + " Tier " + tier + "\n"));
}
addCategory(p, profile, category, lines);
}
}
openBook(p, profile, lines, false);
}
private void addCategory(Player p, PlayerProfile profile, Category category, List<ChatComponent> lines) {
if (category instanceof LockedCategory && !((LockedCategory) category).hasUnlocked(p, profile)) {
List<String> lore = new LinkedList<>();
lore.add(ChatColor.DARK_RED + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked") + " " + ChatColor.GRAY + "- " + ChatColor.RESET + category.getItem(p).getItemMeta().getDisplayName());
lore.add("");
for (String line : SlimefunPlugin.getLocalization().getMessages(p, "guide.locked-category")) {
lore.add(ChatColor.RESET + line);
}
lore.add("");
for (Category parent : ((LockedCategory) category).getParents()) {
lore.add(parent.getItem(p).getItemMeta().getDisplayName());
}
ChatComponent chatComponent = new ChatComponent(ChatUtils.crop(ChatColor.RED, ItemUtils.getItemName(category.getItem(p))) + "\n");
chatComponent.setHoverEvent(new HoverEvent(lore));
lines.add(chatComponent);
} else {
ChatComponent chatComponent = new ChatComponent(ChatUtils.crop(ChatColor.DARK_GREEN, ItemUtils.getItemName(category.getItem(p))) + "\n");
chatComponent.setHoverEvent(new HoverEvent(ItemUtils.getItemName(category.getItem(p)), "", ChatColor.GRAY + "\u21E8 " + ChatColor.GREEN + SlimefunPlugin.getLocalization().getMessage(p, "guide.tooltips.open-category")));
chatComponent.setClickEvent(new ClickEvent(category.getKey(), pl -> openCategory(profile, category, 1)));
lines.add(chatComponent);
}
}
@Override
public void openCategory(PlayerProfile profile, Category category, int page) {
Player p = profile.getPlayer();
if (p == null) {
return;
}
if (category instanceof FlexCategory) {
((FlexCategory) category).open(p, profile, getLayout());
} else if (category.getItems().size() < 250) {
profile.getGuideHistory().add(category, page);
List<ChatComponent> items = new LinkedList<>();
for (SlimefunItem slimefunItem : category.getItems()) {
if (Slimefun.hasPermission(p, slimefunItem, false)) {
if (Slimefun.isEnabled(p, slimefunItem, false)) {
addSlimefunItem(category, page, p, profile, slimefunItem, items);
}
} else {
ChatComponent component = new ChatComponent(ChatUtils.crop(ChatColor.DARK_RED, ItemUtils.getItemName(slimefunItem.getItem())) + "\n");
List<String> lore = new ArrayList<>();
lore.add(ChatColor.DARK_RED + ChatColor.stripColor(ItemUtils.getItemName(slimefunItem.getItem())));
lore.add("");
for (String line : SlimefunPlugin.getPermissionsService().getLore(slimefunItem)) {
lore.add(ChatColors.color(line));
}
component.setHoverEvent(new HoverEvent(lore));
items.add(component);
}
}
openBook(p, profile, items, true);
} else {
p.sendMessage(ChatColor.RED + "That Category is too big to open :/");
}
}
private void addSlimefunItem(Category category, int page, Player p, PlayerProfile profile, SlimefunItem item, List<ChatComponent> items) {
NamespacedKey key = new NamespacedKey(SlimefunPlugin.instance(), item.getId().toLowerCase(Locale.ROOT));
if (!Slimefun.hasUnlocked(p, item, false) && item.getResearch() != null) {
Research research = item.getResearch();
ChatComponent component = new ChatComponent(ChatUtils.crop(ChatColor.RED, item.getItemName()) + "\n");
component.setHoverEvent(new HoverEvent(ChatColor.RESET + item.getItemName(), ChatColor.DARK_RED.toString() + ChatColor.BOLD + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked"), "", ChatColor.GREEN + "> Click to unlock", "", ChatColor.GRAY + "Cost: " + ChatColor.AQUA.toString() + research.getCost() + " Level(s)"));
component.setClickEvent(new ClickEvent(key, player -> SlimefunPlugin.runSync(() -> research.unlockFromGuide(this, player, profile, item, category, page))));
items.add(component);
} else {
ChatComponent component = new ChatComponent(ChatUtils.crop(ChatColor.DARK_GREEN, item.getItemName()) + "\n");
List<String> lore = new ArrayList<>();
lore.add(item.getItemName());
if (item.getItem().hasItemMeta() && item.getItem().getItemMeta().hasLore()) {
lore.addAll(item.getItem().getItemMeta().getLore());
}
component.setHoverEvent(new HoverEvent(lore));
component.setClickEvent(new ClickEvent(key, player -> SlimefunPlugin.runSync(() -> displayItem(profile, item, true))));
items.add(component);
}
}
@Override
public void openSearch(PlayerProfile profile, String input, boolean addToHistory) {
// We need to write a book implementation for this at some point
SlimefunGuide.openSearch(profile, input, true, addToHistory);
}
@Override
public void displayItem(PlayerProfile profile, ItemStack item, int index, boolean addToHistory) {
SlimefunGuide.displayItem(profile, item, addToHistory);
}
@Override
public void displayItem(PlayerProfile profile, SlimefunItem item, boolean addToHistory) {
SlimefunGuide.displayItem(profile, item, addToHistory);
}
}

View File

@ -12,7 +12,7 @@ import org.bukkit.inventory.Recipe;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.SlimefunGuideItem;
@ -21,13 +21,13 @@ import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
/**
* This is an admin-variant of the {@link ChestSlimefunGuide} which allows a {@link Player}
* This is an admin-variant of the {@link SurvivalSlimefunGuide} which allows a {@link Player}
* to spawn in a {@link SlimefunItem} via click rather than showing their {@link Recipe}.
*
* @author TheBusyBiscuit
*
*/
public class CheatSheetSlimefunGuide extends ChestSlimefunGuide {
public class CheatSheetSlimefunGuide extends SurvivalSlimefunGuide {
private final ItemStack item;
@ -37,11 +37,6 @@ public class CheatSheetSlimefunGuide extends ChestSlimefunGuide {
item = new SlimefunGuideItem(this, "&cSlimefun Guide &4(Cheat Sheet)");
}
@Override
public boolean isSurvivalMode() {
return false;
}
/**
* Returns a {@link List} of visible {@link Category} instances that the {@link SlimefunGuide} would display.
*
@ -65,11 +60,13 @@ public class CheatSheetSlimefunGuide extends ChestSlimefunGuide {
return categories;
}
@Nonnull
@Override
public SlimefunGuideLayout getLayout() {
return SlimefunGuideLayout.CHEAT_SHEET;
public SlimefunGuideMode getMode() {
return SlimefunGuideMode.CHEAT_MODE;
}
@Nonnull
@Override
public ItemStack getItem() {
return item;

View File

@ -21,7 +21,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
* A {@link RecipeChoiceTask} is an asynchronously repeating task that cycles
* through the different variants of {@link Material} that a {@link MaterialChoice} or {@link Tag} can represent.
*
* It is used in the {@link ChestSlimefunGuide} for any {@link ItemStack} from Minecraft
* It is used in the {@link SurvivalSlimefunGuide} for any {@link ItemStack} from Minecraft
* that accepts more than one {@link Material} in its {@link Recipe}.
*
* @author TheBusyBiscuit

View File

@ -27,6 +27,7 @@ import io.github.thebusybiscuit.cscorelib2.chat.ChatInput;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.recipes.MinecraftRecipe;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory;
@ -34,7 +35,7 @@ import io.github.thebusybiscuit.slimefun4.core.categories.LockedCategory;
import io.github.thebusybiscuit.slimefun4.core.guide.GuideHistory;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideImplementation;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.core.guide.options.SlimefunGuideSettings;
import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlock;
import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlockMachine;
@ -51,18 +52,17 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link ChestSlimefunGuide} is the standard version of our {@link SlimefunGuide}.
* The {@link SurvivalSlimefunGuide} is the standard version of our {@link SlimefunGuide}.
* It uses an {@link Inventory} to display {@link SlimefunGuide} contents.
*
* @author TheBusyBiscuit
*
* @see SlimefunGuide
* @see SlimefunGuideImplementation
* @see BookSlimefunGuide
* @see CheatSheetSlimefunGuide
*
*/
public class ChestSlimefunGuide implements SlimefunGuideImplementation {
public class SurvivalSlimefunGuide implements SlimefunGuideImplementation {
private static final int CATEGORY_SIZE = 36;
private static final Sound sound = Sound.ITEM_BOOK_PAGE_TURN;
@ -71,14 +71,14 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
private final ItemStack item;
private final boolean showVanillaRecipes;
public ChestSlimefunGuide(boolean showVanillaRecipes) {
public SurvivalSlimefunGuide(boolean showVanillaRecipes) {
this.showVanillaRecipes = showVanillaRecipes;
item = new SlimefunGuideItem(this, "&aSlimefun Guide &7(Chest GUI)");
}
@Override
public SlimefunGuideLayout getLayout() {
return SlimefunGuideLayout.CHEST;
public SlimefunGuideMode getMode() {
return SlimefunGuideMode.SURVIVAL_MODE;
}
@Override
@ -86,9 +86,8 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
return item;
}
@Override
public boolean isSurvivalMode() {
return true;
protected final boolean isSurvivalMode() {
return getMode() != SlimefunGuideMode.CHEAT_MODE;
}
/**
@ -105,8 +104,18 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
List<Category> categories = new LinkedList<>();
for (Category category : SlimefunPlugin.getRegistry().getCategories()) {
if (!category.isHidden(p) && (!(category instanceof FlexCategory) || ((FlexCategory) category).isVisible(p, profile, getLayout()))) {
categories.add(category);
try {
if (!category.isHidden(p) && (!(category instanceof FlexCategory) || ((FlexCategory) category).isVisible(p, profile, getMode()))) {
categories.add(category);
}
} catch (Exception | LinkageError x) {
SlimefunAddon addon = category.getAddon();
if (addon != null) {
addon.getLogger().log(Level.SEVERE, x, () -> "Could not display Category: " + category);
} else {
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "Could not display Category: " + category);
}
}
}
@ -204,7 +213,7 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
}
if (category instanceof FlexCategory) {
((FlexCategory) category).open(p, profile, getLayout());
((FlexCategory) category).open(p, profile, getMode());
return;
}
@ -698,7 +707,7 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
private void printErrorMessage(Player p, Throwable x) {
p.sendMessage(ChatColor.DARK_RED + "An internal server error has occurred. Please inform an admin, check the console for further info.");
Slimefun.getLogger().log(Level.SEVERE, "An error has occurred while trying to open a SlimefunItem in the guide!", x);
SlimefunPlugin.logger().log(Level.SEVERE, "An error has occurred while trying to open a SlimefunItem in the guide!", x);
}
}

View File

@ -1,55 +0,0 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.androids;
import java.util.Optional;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Effect;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
/**
* The {@link AdvancedFarmerAndroid} is an extension of the {@link FarmerAndroid}.
* It also allows the {@link Player} to harvest plants from the addon ExoticGarden.
*
* @author John000708
* @author TheBusyBiscuit
*
* @see FarmerAndroid
*
*/
public class AdvancedFarmerAndroid extends FarmerAndroid {
@ParametersAreNonnullByDefault
public AdvancedFarmerAndroid(Category category, int tier, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, tier, item, recipeType, recipe);
}
@Override
public AndroidType getAndroidType() {
return AndroidType.ADVANCED_FARMER;
}
@Override
protected void exoticFarm(BlockMenu menu, Block block) {
farm(menu, block);
if (SlimefunPlugin.getIntegrations().isExoticGardenInstalled()) {
Optional<ItemStack> result = SlimefunPlugin.getThirdPartySupportService().harvestExoticGardenPlant(block);
if (result.isPresent()) {
ItemStack drop = result.get();
menu.pushItem(drop, getOutputSlots());
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType());
}
}
}
}

View File

@ -29,7 +29,7 @@ public enum AndroidType {
FARMER,
/**
* The {@link AdvancedFarmerAndroid} is an extension of the {@link FarmerAndroid},
* The Advanced Farmer is an extension of the {@link FarmerAndroid},
* it can also harvest plants from ExoticGarden.
*/
ADVANCED_FARMER,

View File

@ -3,6 +3,9 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.androids;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.Material;
import org.bukkit.block.Block;
@ -10,6 +13,7 @@ import org.bukkit.block.data.Ageable;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.events.AndroidFarmEvent;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
@ -17,37 +21,41 @@ import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
public class FarmerAndroid extends ProgrammableAndroid {
@ParametersAreNonnullByDefault
public FarmerAndroid(Category category, int tier, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, tier, item, recipeType, recipe);
}
@Override
public AndroidType getAndroidType() {
return AndroidType.FARMER;
}
private boolean isFullGrown(Block block) {
BlockData data = block.getBlockData();
if (!(data instanceof Ageable)) {
return false;
}
Ageable ageable = (Ageable) data;
return ageable.getAge() >= ageable.getMaximumAge();
return getTier() == 1 ? AndroidType.FARMER : AndroidType.ADVANCED_FARMER;
}
@Override
protected void farm(BlockMenu menu, Block block) {
if (isFullGrown(block)) {
ItemStack drop = getDropFromCrop(block.getType());
protected void farm(Block b, BlockMenu menu, Block block, boolean isAdvanced) {
Material blockType = block.getType();
BlockData data = block.getBlockData();
ItemStack drop = null;
if (drop != null && menu.fits(drop, getOutputSlots())) {
menu.pushItem(drop, getOutputSlots());
Ageable ageable = (Ageable) block.getBlockData();
ageable.setAge(0);
block.setBlockData(ageable);
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType());
if (data instanceof Ageable && ((Ageable) data).getAge() >= ((Ageable) data).getMaximumAge()) {
drop = getDropFromCrop(blockType);
}
AndroidInstance instance = new AndroidInstance(this, b);
AndroidFarmEvent event = new AndroidFarmEvent(block, instance, isAdvanced, drop);
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
drop = event.getDrop();
if (drop != null && menu.pushItem(drop, getOutputSlots()) == null) {
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, blockType);
if (data instanceof Ageable) {
((Ageable) data).setAge(0);
block.setBlockData(data);
}
}
}
}

View File

@ -1,11 +1,12 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.androids;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
import org.apache.commons.lang.Validate;
import org.bukkit.Location;
@ -191,7 +192,7 @@ public enum Instruction {
*/
FARM_FORWARD(AndroidType.FARMER, HeadTexture.SCRIPT_FARM_FORWARD, (android, b, inv, face) -> {
Block target = b.getRelative(face);
android.farm(inv, target);
android.farm(b, inv, target, false);
}),
/**
@ -200,7 +201,7 @@ public enum Instruction {
*/
FARM_DOWN(AndroidType.FARMER, HeadTexture.SCRIPT_FARM_DOWN, (android, b, inv, face) -> {
Block target = b.getRelative(BlockFace.DOWN);
android.farm(inv, target);
android.farm(b, inv, target, false);
}),
/**
@ -211,7 +212,7 @@ public enum Instruction {
*/
FARM_EXOTIC_FORWARD(AndroidType.ADVANCED_FARMER, HeadTexture.SCRIPT_FARM_FORWARD, (android, b, inv, face) -> {
Block target = b.getRelative(face);
android.exoticFarm(inv, target);
android.farm(b, inv, target, true);
}),
/**
@ -222,7 +223,7 @@ public enum Instruction {
*/
FARM_EXOTIC_DOWN(AndroidType.ADVANCED_FARMER, HeadTexture.SCRIPT_FARM_DOWN, (android, b, inv, face) -> {
Block target = b.getRelative(BlockFace.DOWN);
android.exoticFarm(inv, target);
android.farm(b, inv, target, true);
}),
/**

View File

@ -58,7 +58,6 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
@ -425,7 +424,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
openScriptEditor(player, b);
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, "An Exception was thrown when a User tried to download a Script!", x);
SlimefunPlugin.logger().log(Level.SEVERE, "An Exception was thrown when a User tried to download a Script!", x);
}
return false;
@ -881,11 +880,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
throw new UnsupportedOperationException("Non-woodcutter Android tried to chop a Tree!");
}
protected void farm(BlockMenu menu, Block block) {
throw new UnsupportedOperationException("Non-farming Android tried to farm!");
}
protected void exoticFarm(BlockMenu menu, Block block) {
protected void farm(Block b, BlockMenu menu, Block block, boolean isAdvanced) {
throw new UnsupportedOperationException("Non-farming Android tried to farm!");
}

View File

@ -21,9 +21,9 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.config.Config;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* A {@link Script} represents runnable code for a {@link ProgrammableAndroid}.
@ -244,7 +244,7 @@ public final class Script {
scripts.add(new Script(config));
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Exception occurred while trying to load Android Script '" + file.getName() + "'");
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Exception occurred while trying to load Android Script '" + file.getName() + "'");
}
}
}

View File

@ -11,12 +11,12 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import io.github.thebusybiscuit.slimefun4.utils.holograms.SimpleHologram;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -89,9 +89,9 @@ public class HologramProjector extends SlimefunItem {
return false;
});
menu.addItem(1, new CustomItem(Material.CLOCK, "&7Offset: &e" + DoubleHandler.fixDouble(Double.valueOf(BlockStorage.getLocationInfo(projector.getLocation(), OFFSET_PARAMETER)) + 1.0D), "", "&rLeft Click: &7+0.1", "&rRight Click: &7-0.1"));
menu.addItem(1, new CustomItem(Material.CLOCK, "&7Offset: &e" + NumberUtils.roundDecimalNumber(Double.valueOf(BlockStorage.getLocationInfo(projector.getLocation(), OFFSET_PARAMETER)) + 1.0D), "", "&rLeft Click: &7+0.1", "&rRight Click: &7-0.1"));
menu.addMenuClickHandler(1, (pl, slot, item, action) -> {
double offset = DoubleHandler.fixDouble(Double.valueOf(BlockStorage.getLocationInfo(projector.getLocation(), OFFSET_PARAMETER)) + (action.isRightClicked() ? -0.1F : 0.1F));
double offset = NumberUtils.reparseDouble(Double.valueOf(BlockStorage.getLocationInfo(projector.getLocation(), OFFSET_PARAMETER)) + (action.isRightClicked() ? -0.1F : 0.1F));
ArmorStand hologram = getArmorStand(projector, true);
Location l = new Location(projector.getWorld(), projector.getX() + 0.5, projector.getY() + offset, projector.getZ() + 0.5);
hologram.teleport(l);

View File

@ -14,7 +14,6 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetProvider;
import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
@ -114,7 +113,7 @@ public abstract class AbstractEnergyProvider extends SlimefunItem implements Inv
List<String> lore = new ArrayList<>();
lore.add(ChatColors.color("&8\u21E8 &7Lasts " + NumberUtils.getTimeLeft(fuel.getTicks() / 2)));
lore.add(ChatColors.color("&8\u21E8 &e\u26A1 &7" + getEnergyProduction() * 2) + " J/s");
lore.add(ChatColors.color("&8\u21E8 &e\u26A1 &7" + DoubleHandler.getFancyDouble((double) fuel.getTicks() * getEnergyProduction()) + " J in total"));
lore.add(ChatColors.color("&8\u21E8 &e\u26A1 &7" + NumberUtils.getCompactDouble((double) fuel.getTicks() * getEnergyProduction()) + " J in total"));
im.setLore(lore);
item.setItemMeta(im);
list.add(item);

View File

@ -11,7 +11,6 @@ import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.events.BlockPlacerPlaceEvent;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
@ -20,6 +19,7 @@ import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponen
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -166,7 +166,7 @@ public abstract class AbstractEntityAssembler<T extends Entity> extends SimpleSl
menu.replaceExistingItem(31, new CustomItem(Material.PISTON, "&7Offset: &3" + offset + " Block(s)", "", "&fLeft Click: &7+0.1", "&fRight Click: &7-0.1"));
menu.addMenuClickHandler(31, (p, slot, item, action) -> {
double offsetv = DoubleHandler.fixDouble(Double.valueOf(BlockStorage.getLocationInfo(b.getLocation(), KEY_OFFSET)) + (action.isRightClicked() ? -0.1F : 0.1F));
double offsetv = NumberUtils.reparseDouble(Double.valueOf(BlockStorage.getLocationInfo(b.getLocation(), KEY_OFFSET)) + (action.isRightClicked() ? -0.1F : 0.1F));
BlockStorage.addBlockInfo(b, KEY_OFFSET, String.valueOf(offsetv));
updateBlockInventory(menu, b);
return false;

View File

@ -0,0 +1,93 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.elevator;
import javax.annotation.Nonnull;
import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
/**
* This represents an {@link ElevatorFloor} to which a {@link Player}
* can travel to using an {@link ElevatorPlate}.
*
* @author TheBusyBiscuit
*
*/
class ElevatorFloor {
/**
* The name of this floor.
*/
private final String name;
/**
* The floor number.
*/
private final int number;
/**
* The {@link Location} of this floor.
*/
private final Location location;
/**
* This constructs a new {@link ElevatorFloor} with the given name
* and the {@link Location} of the provided {@link Block}.
*
* @param name
* The name of this {@link ElevatorFloor}
* @param block
* The {@link Block} of this floor
*/
public ElevatorFloor(@Nonnull String name, int number, @Nonnull Block block) {
Validate.notNull(name, "An ElevatorFloor must have a name");
Validate.notNull(block, "An ElevatorFloor must have a block");
this.name = name;
this.number = number;
this.location = block.getLocation();
}
/**
* This returns the name of this {@link ElevatorFloor}.
*
* @return The name of this floor
*/
@Nonnull
public String getName() {
return name;
}
/**
* This returns the {@link Location} of this {@link ElevatorFloor}.
*
* @return The {@link Location} of this floor
*/
@Nonnull
public Location getLocation() {
return location;
}
/**
* This returns the "altitude" of this floor.
* This is equivalent to the Y level of {@link #getLocation()}.
*
* @return The altitude of this floor
*/
public int getAltitude() {
return location.getBlockY();
}
/**
* This returns the number of this floor.
* The lowest floor will have the number 0 and it
* increments from there.
*
* @return The number of this floor.
*/
public int getNumber() {
return number;
}
}

View File

@ -1,4 +1,4 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.gps;
package io.github.thebusybiscuit.slimefun4.implementation.items.elevator;
import java.util.HashSet;
import java.util.LinkedList;
@ -12,22 +12,19 @@ import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.chat.json.ChatComponent;
import io.github.thebusybiscuit.cscorelib2.chat.json.ClickEvent;
import io.github.thebusybiscuit.cscorelib2.chat.json.CustomBookInterface;
import io.github.thebusybiscuit.cscorelib2.chat.json.HoverEvent;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
@ -40,9 +37,9 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
* The {@link ElevatorPlate} is a quick way of teleportation.
* You can place multiple {@link ElevatorPlate ElevatorPlates} along the y axis
* to teleport between them.
*
* @author TheBusyBiscuit
*
* @author TheBusyBiscuit
* @author Walshy
*/
public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
@ -51,6 +48,11 @@ public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
*/
private static final String DATA_KEY = "floor";
/**
* This is the size of our {@link Inventory}.
*/
private static final int GUI_SIZE = 27;
/**
* This is our {@link Set} of currently teleporting {@link Player Players}.
* It is used to prevent them from triggering the {@link ElevatorPlate} they land on.
@ -77,6 +79,7 @@ public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
};
}
@Nonnull
@Override
public BlockUseHandler getItemHandler() {
return e -> {
@ -89,19 +92,24 @@ public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
}
@Nonnull
public List<Block> getFloors(@Nonnull Block b) {
List<Block> floors = new LinkedList<>();
public List<ElevatorFloor> getFloors(@Nonnull Block b) {
LinkedList<ElevatorFloor> floors = new LinkedList<>();
int index = 0;
for (int y = b.getWorld().getMaxHeight(); y > 0; y--) {
for (int y = 0; y < b.getWorld().getMaxHeight(); y++) {
if (y == b.getY()) {
floors.add(b);
String name = ChatColors.color(BlockStorage.getLocationInfo(b.getLocation(), DATA_KEY));
floors.addFirst(new ElevatorFloor(name, index, b));
index++;
continue;
}
Block block = b.getWorld().getBlockAt(b.getX(), y, b.getZ());
if (block.getType() == getItem().getType() && BlockStorage.check(block, getId())) {
floors.add(block);
String name = ChatColors.color(BlockStorage.getLocationInfo(block.getLocation(), DATA_KEY));
floors.addFirst(new ElevatorFloor(name, index, block));
index++;
}
}
@ -114,54 +122,69 @@ public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
return;
}
List<Block> floors = getFloors(b);
List<ElevatorFloor> floors = getFloors(b);
if (floors.size() < 2) {
SlimefunPlugin.getLocalization().sendMessage(p, "machines.ELEVATOR.no-destinations", true);
} else {
openFloorSelector(b, floors, p);
openFloorSelector(b, floors, p, 1);
}
}
@ParametersAreNonnullByDefault
private void openFloorSelector(Block b, List<Block> floors, Player p) {
CustomBookInterface book = new CustomBookInterface(SlimefunPlugin.instance());
ChatComponent page = null;
private void openFloorSelector(Block b, List<ElevatorFloor> floors, Player p, int page) {
ChestMenu menu = new ChestMenu(SlimefunPlugin.getLocalization().getMessage(p, "machines.ELEVATOR.pick-a-floor"));
menu.setEmptySlotsClickable(false);
for (int i = 0; i < floors.size(); i++) {
if (i % 10 == 0) {
if (page != null) {
book.addPage(page);
}
int index = GUI_SIZE * (page - 1);
page = new ChatComponent(ChatColors.color(SlimefunPlugin.getLocalization().getMessage(p, "machines.ELEVATOR.pick-a-floor")) + "\n");
}
for (int i = 0; i < Math.min(GUI_SIZE, floors.size() - index); i++) {
ElevatorFloor floor = floors.get(index + i);
Block block = floors.get(i);
String floor = ChatColors.color(BlockStorage.getLocationInfo(block.getLocation(), DATA_KEY));
ChatComponent line;
if (block.getY() == b.getY()) {
line = new ChatComponent("\n" + ChatColor.GRAY + "> " + (floors.size() - i) + ". " + ChatColor.BLACK + floor);
line.setHoverEvent(new HoverEvent(ChatColors.color(SlimefunPlugin.getLocalization().getMessage(p, "machines.ELEVATOR.current-floor")), "", ChatColor.WHITE + floor, ""));
// @formatter:off
if (floor.getAltitude() == b.getY()) {
menu.addItem(i, new CustomItem(
Material.COMPASS,
ChatColor.GRAY.toString() + floor.getNumber() + ". " + ChatColor.BLACK + floor.getName(),
SlimefunPlugin.getLocalization().getMessage(p, "machines.ELEVATOR.current-floor") + ' ' + ChatColor.WHITE + floor.getName()
), ChestMenuUtils.getEmptyClickHandler());
} else {
line = new ChatComponent("\n" + ChatColor.GRAY + (floors.size() - i) + ". " + ChatColor.BLACK + floor);
line.setHoverEvent(new HoverEvent(ChatColors.color(SlimefunPlugin.getLocalization().getMessage(p, "machines.ELEVATOR.click-to-teleport")), "", ChatColor.WHITE + floor, ""));
line.setClickEvent(new ClickEvent(new NamespacedKey(SlimefunPlugin.instance(), DATA_KEY + i), player -> teleport(player, floor, block)));
menu.addItem(i, new CustomItem(
Material.PAPER,
ChatColor.GRAY.toString() + floor.getNumber() + ". " + ChatColor.BLACK + floor.getName(),
SlimefunPlugin.getLocalization().getMessage(p, "machines.ELEVATOR.click-to-teleport") + ' ' + ChatColor.WHITE + floor.getName()
), (player, slot, itemStack, clickAction) -> {
teleport(player, floor);
return false;
});
}
page.append(line);
// @formatter:on
}
if (page != null) {
book.addPage(page);
int pages = 1 + (floors.size() / GUI_SIZE);
// 0 index so size is the first slot of the last row.
for (int i = GUI_SIZE; i < GUI_SIZE + 9; i++) {
if (i == GUI_SIZE + 2 && pages > 1 && page != 1) {
menu.addItem(i, ChestMenuUtils.getPreviousButton(p, page, pages), (player, i1, itemStack, clickAction) -> {
openFloorSelector(b, floors, p, page - 1);
return false;
});
} else if (i == GUI_SIZE + 6 && pages > 1 && page != pages) {
menu.addItem(i, ChestMenuUtils.getNextButton(p, page, pages), (player, i1, itemStack, clickAction) -> {
openFloorSelector(b, floors, p, page + 1);
return false;
});
} else {
menu.addItem(i, ChestMenuUtils.getBackground(), (player, i1, itemStack, clickAction) -> false);
}
}
book.open(p);
menu.open(p);
}
@ParametersAreNonnullByDefault
private void teleport(Player player, String floorName, Block target) {
private void teleport(Player player, ElevatorFloor floor) {
SlimefunPlugin.runSync(() -> {
users.add(player.getUniqueId());
@ -171,11 +194,12 @@ public class ElevatorPlate extends SimpleSlimefunItem<BlockUseHandler> {
yaw = -180 + (yaw - 180);
}
Location destination = new Location(player.getWorld(), target.getX() + 0.5, target.getY() + 0.4, target.getZ() + 0.5, yaw, player.getEyeLocation().getPitch());
Location loc = floor.getLocation();
Location destination = new Location(player.getWorld(), loc.getX() + 0.5, loc.getY() + 0.4, loc.getZ() + 0.5, yaw, player.getEyeLocation().getPitch());
PaperLib.teleportAsync(player, destination).thenAccept(teleported -> {
if (teleported.booleanValue()) {
player.sendTitle(ChatColor.WHITE + ChatColors.color(floorName), null, 20, 60, 20);
player.sendTitle(ChatColor.WHITE + ChatColors.color(floor.getName()), null, 20, 60, 20);
}
});
});

View File

@ -0,0 +1,5 @@
/**
* This package holds the {@link io.github.thebusybiscuit.slimefun4.implementation.items.elevator.ElevatorPlate} and any
* related classes to making the elevator work.
*/
package io.github.thebusybiscuit.slimefun4.implementation.items.elevator;

View File

@ -17,8 +17,8 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.settings.TalismanEnchantment;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
@ -42,7 +42,7 @@ public class MagicianTalisman extends Talisman {
enchantments.add(new TalismanEnchantment(enchantment, i));
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "The following Exception occurred while trying to register the following Enchantment: " + enchantment);
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "The following Exception occurred while trying to register the following Enchantment: " + enchantment);
}
}

View File

@ -27,7 +27,6 @@ import io.github.thebusybiscuit.cscorelib2.scheduling.TaskQueue;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This represents a running instance of an {@link IndustrialMiner}.
@ -198,7 +197,7 @@ class ActiveMiner implements Runnable {
nextColumn();
} catch (Exception e) {
Slimefun.getLogger().log(Level.SEVERE, e, () -> "An Error occurred while running an Industrial Miner at " + new BlockPosition(chest));
SlimefunPlugin.logger().log(Level.SEVERE, e, () -> "An Error occurred while running an Industrial Miner at " + new BlockPosition(chest));
stop();
}
});
@ -350,7 +349,7 @@ class ActiveMiner implements Runnable {
stop("machines.INDUSTRIAL_MINER.destroyed");
}
} catch (Exception e) {
Slimefun.getLogger().log(Level.SEVERE, e, () -> "An Error occurred while moving a Piston for an Industrial Miner at " + new BlockPosition(block));
SlimefunPlugin.logger().log(Level.SEVERE, e, () -> "An Error occurred while moving a Piston for an Industrial Miner at " + new BlockPosition(block));
stop();
}
}

View File

@ -29,7 +29,6 @@ import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This {@link Listener} is responsible for handling our debugging tool, the debug fish.
@ -99,7 +98,7 @@ public class DebugFishListener implements Listener {
try {
sendInfo(p, b);
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, "An Exception occurred while using a Debug-Fish", x);
SlimefunPlugin.logger().log(Level.SEVERE, "An Exception occurred while using a Debug-Fish", x);
}
}
}

View File

@ -12,10 +12,10 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.events.SlimefunGuideOpenEvent;
import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent;
import io.github.thebusybiscuit.slimefun4.api.events.SlimefunGuideOpenEvent;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.core.guide.options.SlimefunGuideSettings;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
@ -38,7 +38,7 @@ public class SlimefunGuideListener implements Listener {
return;
}
SlimefunGuideLayout type = SlimefunGuide.getDefaultLayout();
SlimefunGuideMode type = SlimefunGuide.getDefaultLayout();
p.getInventory().addItem(SlimefunGuide.getItem(type).clone());
}
}
@ -47,31 +47,27 @@ public class SlimefunGuideListener implements Listener {
public void onInteract(PlayerRightClickEvent e) {
Player p = e.getPlayer();
if (tryOpenGuide(p, e, SlimefunGuideLayout.BOOK) == Result.ALLOW) {
if (tryOpenGuide(p, e, SlimefunGuideMode.SURVIVAL_MODE) == Result.ALLOW) {
if (p.isSneaking()) {
SlimefunGuideSettings.openSettings(p, e.getItem());
} else {
openGuide(p, e, SlimefunGuideLayout.BOOK);
openGuide(p, e, SlimefunGuideMode.SURVIVAL_MODE);
}
} else if (tryOpenGuide(p, e, SlimefunGuideLayout.CHEST) == Result.ALLOW) {
} else if (tryOpenGuide(p, e, SlimefunGuideMode.CHEAT_MODE) == Result.ALLOW) {
if (p.isSneaking()) {
SlimefunGuideSettings.openSettings(p, e.getItem());
} else {
openGuide(p, e, SlimefunGuideLayout.CHEST);
}
} else if (tryOpenGuide(p, e, SlimefunGuideLayout.CHEAT_SHEET) == Result.ALLOW) {
if (p.isSneaking()) {
SlimefunGuideSettings.openSettings(p, e.getItem());
} else {
// We rather just run the command here,
// all necessary permission checks will be handled there.
/*
* We rather just run the command here, all
* necessary permission checks will be handled there.
*/
p.chat("/sf cheat");
}
}
}
@ParametersAreNonnullByDefault
private void openGuide(Player p, PlayerRightClickEvent e, SlimefunGuideLayout layout) {
private void openGuide(Player p, PlayerRightClickEvent e, SlimefunGuideMode layout) {
SlimefunGuideOpenEvent event = new SlimefunGuideOpenEvent(p, e.getItem(), layout);
Bukkit.getPluginManager().callEvent(event);
@ -83,7 +79,7 @@ public class SlimefunGuideListener implements Listener {
@Nonnull
@ParametersAreNonnullByDefault
private Result tryOpenGuide(Player p, PlayerRightClickEvent e, SlimefunGuideLayout layout) {
private Result tryOpenGuide(Player p, PlayerRightClickEvent e, SlimefunGuideMode layout) {
ItemStack item = e.getItem();
if (SlimefunUtils.isItemSimilar(item, SlimefunGuide.getItem(layout), true, false)) {

View File

@ -15,7 +15,7 @@ import org.bukkit.event.player.PlayerInteractEvent;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.ElevatorPlate;
import io.github.thebusybiscuit.slimefun4.implementation.items.elevator.ElevatorPlate;
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.Teleporter;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;

View File

@ -11,7 +11,6 @@ import org.bukkit.event.world.WorldUnloadEvent;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
public class WorldListener implements Listener {
@ -32,7 +31,7 @@ public class WorldListener implements Listener {
if (storage != null) {
storage.saveAndRemove();
} else {
Slimefun.getLogger().log(Level.SEVERE, "Could not save Slimefun Blocks for World \"{0}\"", e.getWorld().getName());
SlimefunPlugin.logger().log(Level.SEVERE, "Could not save Slimefun Blocks for World \"{0}\"", e.getWorld().getName());
}
}

View File

@ -35,14 +35,13 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.Smelt
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
import me.mrCookieSlime.Slimefun.api.Slimefun;
public final class PostSetup {
private PostSetup() {}
public static void setupWiki() {
Slimefun.getLogger().log(Level.INFO, "Loading Wiki pages...");
SlimefunPlugin.logger().log(Level.INFO, "Loading Wiki pages...");
JsonParser parser = new JsonParser();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(SlimefunPlugin.class.getResourceAsStream("/wiki.json"), StandardCharsets.UTF_8))) {
@ -57,7 +56,7 @@ public final class PostSetup {
}
}
} catch (IOException e) {
Slimefun.getLogger().log(Level.SEVERE, "Failed to load wiki.json file", e);
SlimefunPlugin.logger().log(Level.SEVERE, "Failed to load wiki.json file", e);
}
}
@ -68,7 +67,7 @@ public final class PostSetup {
SlimefunItem item = iterator.next();
if (item == null) {
Slimefun.getLogger().log(Level.WARNING, "Removed bugged Item ('NULL?')");
SlimefunPlugin.logger().log(Level.WARNING, "Removed bugged Item ('NULL?')");
iterator.remove();
} else {
try {

View File

@ -25,7 +25,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.RadioactiveItem;
import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem;
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientAltar;
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientPedestal;
import io.github.thebusybiscuit.slimefun4.implementation.items.androids.AdvancedFarmerAndroid;
import io.github.thebusybiscuit.slimefun4.implementation.items.androids.AndroidInterface;
import io.github.thebusybiscuit.slimefun4.implementation.items.androids.ButcherAndroid;
import io.github.thebusybiscuit.slimefun4.implementation.items.androids.FarmerAndroid;
@ -110,6 +109,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.XPCollector;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.reactors.NetherStarReactor;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.reactors.NuclearReactor;
import io.github.thebusybiscuit.slimefun4.implementation.items.elevator.ElevatorPlate;
import io.github.thebusybiscuit.slimefun4.implementation.items.food.BirthdayCake;
import io.github.thebusybiscuit.slimefun4.implementation.items.food.DietCookie;
import io.github.thebusybiscuit.slimefun4.implementation.items.food.FortuneCookie;
@ -122,7 +122,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.geo.GEOMiner;
import io.github.thebusybiscuit.slimefun4.implementation.items.geo.GEOScanner;
import io.github.thebusybiscuit.slimefun4.implementation.items.geo.OilPump;
import io.github.thebusybiscuit.slimefun4.implementation.items.geo.PortableGEOScanner;
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.ElevatorPlate;
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.GPSControlPanel;
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.GPSMarkerTool;
import io.github.thebusybiscuit.slimefun4.implementation.items.gps.GPSTransmitter;
@ -1895,7 +1894,7 @@ public final class SlimefunItemSetup {
new ItemStack[] {null, SlimefunItems.GPS_TRANSMITTER, null, new ItemStack(Material.DIAMOND_SWORD), SlimefunItems.PROGRAMMABLE_ANDROID_2, new ItemStack(Material.DIAMOND_SWORD), null, SlimefunItems.ELECTRIC_MOTOR, null})
.register(plugin);
new AdvancedFarmerAndroid(categories.androids, 2, SlimefunItems.PROGRAMMABLE_ANDROID_2_FARMER, RecipeType.ENHANCED_CRAFTING_TABLE,
new FarmerAndroid(categories.androids, 2, SlimefunItems.PROGRAMMABLE_ANDROID_2_FARMER, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {null, SlimefunItems.GPS_TRANSMITTER, null, new ItemStack(Material.DIAMOND_HOE), SlimefunItems.PROGRAMMABLE_ANDROID_2, new ItemStack(Material.DIAMOND_HOE), null, SlimefunItems.ELECTRIC_MOTOR, null})
.register(plugin);

View File

@ -10,8 +10,8 @@ import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.gadgets.JetBoots;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
public class JetBootsTask extends AbstractPlayerTask {
@ -30,7 +30,7 @@ public class JetBootsTask extends AbstractPlayerTask {
return;
}
double accuracy = DoubleHandler.fixDouble(boots.getSpeed() - 0.7);
double accuracy = NumberUtils.reparseDouble(boots.getSpeed() - 0.7);
if (boots.removeItemCharge(p.getInventory().getBoots(), COST)) {
p.getWorld().playSound(p.getLocation(), Sound.ENTITY_TNT_PRIMED, (float) 0.25, 1);

View File

@ -12,7 +12,6 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.TeleporterLis
import io.github.thebusybiscuit.slimefun4.implementation.setup.PostSetup;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This Task initializes all items, some listeners and various other stuff.
@ -54,7 +53,7 @@ public class SlimefunStartupTask implements Runnable {
try {
new BlockStorage(world);
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Error occurred while trying to load World \"" + world.getName() + "\" for Slimefun v" + SlimefunPlugin.getVersion());
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Error occurred while trying to load World \"" + world.getName() + "\" for Slimefun v" + SlimefunPlugin.getVersion());
}
}

View File

@ -27,7 +27,6 @@ import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link TickerTask} is responsible for ticking every {@link BlockTicker},
@ -132,7 +131,7 @@ public class TickerTask implements Runnable {
reset();
SlimefunPlugin.getProfiler().stop();
} catch (Exception | LinkageError x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Exception was caught while ticking the Block Tickers Task for Slimefun v" + SlimefunPlugin.getVersion());
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Exception was caught while ticking the Block Tickers Task for Slimefun v" + SlimefunPlugin.getVersion());
reset();
}
}
@ -147,7 +146,7 @@ public class TickerTask implements Runnable {
}
}
} catch (ArrayIndexOutOfBoundsException | NumberFormatException x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Exception has occurred while trying to resolve Chunk: " + chunk);
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Exception has occurred while trying to resolve Chunk: " + chunk);
}
}
@ -204,10 +203,10 @@ public class TickerTask implements Runnable {
new ErrorReport<>(x, l, item);
bugs.put(position, errors);
} else if (errors == 4) {
Slimefun.getLogger().log(Level.SEVERE, "X: {0} Y: {1} Z: {2} ({3})", new Object[] { l.getBlockX(), l.getBlockY(), l.getBlockZ(), item.getId() });
Slimefun.getLogger().log(Level.SEVERE, "has thrown 4 error messages in the last 4 Ticks, the Block has been terminated.");
Slimefun.getLogger().log(Level.SEVERE, "Check your /plugins/Slimefun/error-reports/ folder for details.");
Slimefun.getLogger().log(Level.SEVERE, " ");
SlimefunPlugin.logger().log(Level.SEVERE, "X: {0} Y: {1} Z: {2} ({3})", new Object[] { l.getBlockX(), l.getBlockY(), l.getBlockZ(), item.getId() });
SlimefunPlugin.logger().log(Level.SEVERE, "has thrown 4 error messages in the last 4 Ticks, the Block has been terminated.");
SlimefunPlugin.logger().log(Level.SEVERE, "Check your /plugins/Slimefun/error-reports/ folder for details.");
SlimefunPlugin.logger().log(Level.SEVERE, " ");
bugs.remove(position);
BlockStorage.deleteLocationInfoUnsafely(l, true);

View File

@ -14,9 +14,9 @@ import org.bukkit.plugin.Plugin;
import com.gmail.nossr50.events.fake.FakeBlockBreakEvent;
import dev.lone.itemsadder.api.ItemsAdder;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectionManager;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This Service holds all interactions and hooks with third-party {@link Plugin Plugins}
@ -36,6 +36,11 @@ public class IntegrationsManager {
*/
protected final SlimefunPlugin plugin;
/**
* Our {@link ProtectionManager} instance.
*/
private ProtectionManager protectionManager;
/**
* This boolean determines whether {@link #start()} was run.
*/
@ -50,7 +55,6 @@ public class IntegrationsManager {
// Addon support
private boolean isChestTerminalInstalled = false;
private boolean isExoticGardenInstalled = false;
/**
* This initializes the {@link IntegrationsManager}
@ -127,13 +131,27 @@ public class IntegrationsManager {
* This method is called when the {@link Server} has finished loading all its {@link Plugin Plugins}.
*/
private void onServerStart() {
try {
// Load Protection plugin integrations
protectionManager = new ProtectionManager(plugin.getServer());
} catch (Exception | LinkageError x) {
SlimefunPlugin.logger().log(Level.WARNING, x, () -> "Failed to load Protection plugin integrations for Slimefun v" + SlimefunPlugin.getVersion());
}
isChestTerminalInstalled = isAddonInstalled("ChestTerminal");
isExoticGardenInstalled = isAddonInstalled("ExoticGarden");
}
/**
* This method checks if the given addon is installed.
*
* @param addon
* The name of the addon
*
* @return Whether that addon is installed on the {@link Server}
*/
private boolean isAddonInstalled(@Nonnull String addon) {
if (plugin.getServer().getPluginManager().isPluginEnabled(addon)) {
Slimefun.getLogger().log(Level.INFO, "Hooked into Slimefun Addon: {0}", addon);
SlimefunPlugin.logger().log(Level.INFO, "Hooked into Slimefun Addon: {0}", addon);
return true;
} else {
return false;
@ -154,18 +172,29 @@ public class IntegrationsManager {
if (integration != null && integration.isEnabled()) {
String version = integration.getDescription().getVersion();
Slimefun.getLogger().log(Level.INFO, "Hooked into Plugin: {0} v{1}", new Object[] { pluginName, version });
SlimefunPlugin.logger().log(Level.INFO, "Hooked into Plugin: {0} v{1}", new Object[] { pluginName, version });
try {
// Run our callback
consumer.accept(integration);
} catch (Exception | LinkageError x) {
Slimefun.getLogger().log(Level.WARNING, "Maybe consider updating {0} or Slimefun?", pluginName);
Slimefun.getLogger().log(Level.WARNING, x, () -> "Failed to hook into " + pluginName + " v" + version);
SlimefunPlugin.logger().log(Level.WARNING, "Maybe consider updating {0} or Slimefun?", pluginName);
SlimefunPlugin.logger().log(Level.WARNING, x, () -> "Failed to hook into " + pluginName + " v" + version);
}
}
}
/**
* This returns out instance of the {@link ProtectionManager}.
* This bridge is used to hook into any third-party protection {@link Plugin}.
*
* @return Our instanceof of the {@link ProtectionManager}
*/
@Nonnull
public ProtectionManager getProtectionManager() {
return protectionManager;
}
/**
* This checks if one of our third party integrations faked an {@link Event}.
* Faked {@link Event Events} should be ignored in our logic.
@ -218,8 +247,4 @@ public class IntegrationsManager {
return isChestTerminalInstalled;
}
public boolean isExoticGardenInstalled() {
return isExoticGardenInstalled;
}
}

View File

@ -228,6 +228,10 @@ public final class NumberUtils {
return DECIMAL_FORMAT.format(number);
}
public static double reparseDouble(double number) {
return Double.valueOf(roundDecimalNumber(number));
}
public static long getLong(@Nullable Long value, long defaultValue) {
return value == null ? defaultValue : value;
}

View File

@ -47,8 +47,6 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public final class SlimefunUtils {
private static final String NO_PICKUP_METADATA = "no_pickup";
private static final NamespacedKey SOULBOUND_KEY = new NamespacedKey(SlimefunPlugin.instance(), "soulbound");
private static final String SOULBOUND_LORE = ChatColor.GRAY + "Soulbound";
private SlimefunUtils() {}
@ -110,8 +108,9 @@ public final class SlimefunUtils {
private static boolean hasSoulboundFlag(@Nullable ItemMeta meta) {
if (meta != null) {
PersistentDataContainer container = meta.getPersistentDataContainer();
NamespacedKey key = SlimefunPlugin.getRegistry().getSoulboundDataKey();
if (container.has(SOULBOUND_KEY, PersistentDataType.BYTE)) {
if (container.has(key, PersistentDataType.BYTE)) {
return true;
}
}
@ -142,13 +141,14 @@ public final class SlimefunUtils {
ItemMeta meta = item.getItemMeta();
PersistentDataContainer container = meta.getPersistentDataContainer();
NamespacedKey key = SlimefunPlugin.getRegistry().getSoulboundDataKey();
if (makeSoulbound && !isSoulbound) {
container.set(SOULBOUND_KEY, PersistentDataType.BYTE, (byte) 1);
container.set(key, PersistentDataType.BYTE, (byte) 1);
}
if (!makeSoulbound && isSoulbound) {
container.remove(SOULBOUND_KEY);
container.remove(key);
}
List<String> lore = meta.hasLore() ? meta.getLore() : new ArrayList<>();

View File

@ -1,6 +1,6 @@
package io.github.thebusybiscuit.slimefun4.utils.itemstack;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
@ -10,10 +10,11 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.data.PersistentDataAPI;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideImplementation;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.CheatSheetSlimefunGuide;
/**
* This is just a helper {@link ItemStack} class for the {@link SlimefunGuide} {@link ItemStack}.
@ -32,12 +33,15 @@ public class SlimefunGuideItem extends ItemStack {
ItemMeta meta = getItemMeta();
meta.setDisplayName(ChatColors.color(name));
List<String> lore = new LinkedList<>();
lore.add(implementation instanceof CheatSheetSlimefunGuide ? ChatColors.color("&4&lOnly openable by Admins") : "");
List<String> lore = new ArrayList<>();
SlimefunGuideMode type = implementation.getMode();
lore.add(type == SlimefunGuideMode.CHEAT_MODE ? ChatColors.color("&4&lOnly openable by Admins") : "");
lore.add(ChatColors.color("&eRight Click &8\u21E8 &7Browse Items"));
lore.add(ChatColors.color("&eShift + Right Click &8\u21E8 &7Open Settings / Credits"));
meta.setLore(lore);
PersistentDataAPI.setString(meta, SlimefunPlugin.getRegistry().getGuideDataKey(), type.name());
SlimefunPlugin.getItemTextureService().setTexture(meta, "SLIMEFUN_GUIDE");
setItemMeta(meta);

View File

@ -7,6 +7,7 @@ import java.util.Comparator;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
@ -19,6 +20,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.core.categories.LockedCategory;
import io.github.thebusybiscuit.slimefun4.core.categories.SeasonalCategory;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
@ -37,6 +39,8 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
*/
public class Category implements Keyed {
private SlimefunAddon addon;
protected final List<SlimefunItem> items = new ArrayList<>();
protected final NamespacedKey key;
protected final ItemStack item;
@ -94,12 +98,40 @@ public class Category implements Keyed {
* Registers this category.
* <p>
* By default, a category is automatically registered when a {@link SlimefunItem} was added to it.
*
* @param addon
* The {@link SlimefunAddon} that wants to register this {@link Category}
*/
public void register(@Nonnull SlimefunAddon addon) {
Validate.notNull(addon, "The Addon cannot be null");
this.addon = addon;
SlimefunPlugin.getRegistry().getCategories().add(this);
Collections.sort(SlimefunPlugin.getRegistry().getCategories(), Comparator.comparingInt(Category::getTier));
}
/**
* Old way of registering categories, do not call this manually.
*
* @deprecated Please use {@link #register(SlimefunAddon)} instead.
*/
@Deprecated
public void register() {
SlimefunPlugin.getRegistry().getCategories().add(this);
Collections.sort(SlimefunPlugin.getRegistry().getCategories(), Comparator.comparingInt(Category::getTier));
}
/**
* This returns the {@link SlimefunAddon} which has registered this {@link Category}.
* Or null if it has not been registered yet.
*
* @return The {@link SlimefunAddon} or null if unregistered
*/
@Nullable
public final SlimefunAddon getAddon() {
return addon;
}
/**
* Adds the given {@link SlimefunItem} to this {@link Category}.
*

View File

@ -476,7 +476,7 @@ public class SlimefunItem implements Placeable {
private final void onEnable() {
// Register the Category too if it hasn't been registered yet
if (!category.isRegistered()) {
category.register();
category.register(addon);
}
// Send out deprecation warnings for any classes or interfaces

View File

@ -32,8 +32,8 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonWriter;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -97,7 +97,7 @@ public class BlockStorage {
return new Location(w, Integer.parseInt(components[1]), Integer.parseInt(components[2]), Integer.parseInt(components[3]));
}
} catch (NumberFormatException x) {
Slimefun.getLogger().log(Level.WARNING, "Could not parse Number", x);
SlimefunPlugin.logger().log(Level.WARNING, "Could not parse Number", x);
}
return null;
}
@ -114,8 +114,8 @@ public class BlockStorage {
return;
}
Slimefun.getLogger().log(Level.INFO, "Loading Blocks for World \"{0}\"", w.getName());
Slimefun.getLogger().log(Level.INFO, "This may take a long time...");
SlimefunPlugin.logger().log(Level.INFO, "Loading Blocks for World \"{0}\"", w.getName());
SlimefunPlugin.logger().log(Level.INFO, "This may take a long time...");
File dir = new File(PATH_BLOCKS + w.getName());
@ -142,13 +142,13 @@ public class BlockStorage {
try {
for (File file : directory.listFiles()) {
if (file.getName().equals("null.sfb")) {
Slimefun.getLogger().log(Level.WARNING, "File with corrupted blocks detected!");
Slimefun.getLogger().log(Level.WARNING, "Slimefun will simply skip this File, you should look inside though!");
Slimefun.getLogger().log(Level.WARNING, file.getPath());
SlimefunPlugin.logger().log(Level.WARNING, "File with corrupted blocks detected!");
SlimefunPlugin.logger().log(Level.WARNING, "Slimefun will simply skip this File, you should look inside though!");
SlimefunPlugin.logger().log(Level.WARNING, file.getPath());
} else if (file.getName().endsWith(".sfb")) {
if (timestamp + delay < System.currentTimeMillis()) {
int progress = Math.round((((done * 100.0F) / total) * 100.0F) / 100.0F);
Slimefun.getLogger().log(Level.INFO, "Loading Blocks... {0}% done (\"{1}\")", new Object[] { progress, world.getName() });
SlimefunPlugin.logger().log(Level.INFO, "Loading Blocks... {0}% done (\"{1}\")", new Object[] { progress, world.getName() });
timestamp = System.currentTimeMillis();
}
@ -164,11 +164,11 @@ public class BlockStorage {
}
} finally {
long time = (System.currentTimeMillis() - start);
Slimefun.getLogger().log(Level.INFO, "Loading Blocks... 100% (FINISHED - {0}ms)", time);
Slimefun.getLogger().log(Level.INFO, "Loaded a total of {0} Blocks for World \"{1}\"", new Object[] { totalBlocks, world.getName() });
SlimefunPlugin.logger().log(Level.INFO, "Loading Blocks... 100% (FINISHED - {0}ms)", time);
SlimefunPlugin.logger().log(Level.INFO, "Loaded a total of {0} Blocks for World \"{1}\"", new Object[] { totalBlocks, world.getName() });
if (totalBlocks > 0) {
Slimefun.getLogger().log(Level.INFO, "Avg: {0}ms/Block", DoubleHandler.fixDouble((double) time / (double) totalBlocks, 3));
SlimefunPlugin.logger().log(Level.INFO, "Avg: {0}ms/Block", NumberUtils.roundDecimalNumber((double) time / (double) totalBlocks));
}
}
}
@ -193,7 +193,7 @@ public class BlockStorage {
* error to the console (if enabled).
*/
if (SlimefunPlugin.getRegistry().logDuplicateBlockEntries()) {
Slimefun.getLogger().log(Level.INFO, "Ignoring duplicate block @ {0}, {1}, {2} ({3} -> {4})", new Object[] { l.getBlockX(), l.getBlockY(), l.getBlockZ(), blockInfo.getString("id"), storage.get(l).getString("id") });
SlimefunPlugin.logger().log(Level.INFO, "Ignoring duplicate block @ {0}, {1}, {2} ({3} -> {4})", new Object[] { l.getBlockX(), l.getBlockY(), l.getBlockZ(), blockInfo.getString("id"), storage.get(l).getString("id") });
}
return;
@ -206,7 +206,7 @@ public class BlockStorage {
}
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.WARNING, x, () -> "Failed to load " + file.getName() + '(' + key + ") for Slimefun " + SlimefunPlugin.getVersion());
SlimefunPlugin.logger().log(Level.WARNING, x, () -> "Failed to load " + file.getName() + '(' + key + ") for Slimefun " + SlimefunPlugin.getVersion());
}
}
@ -223,7 +223,7 @@ public class BlockStorage {
SlimefunPlugin.getRegistry().getChunks().put(key, data);
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.WARNING, x, () -> "Failed to load " + chunks.getName() + " in World " + world.getName() + '(' + key + ") for Slimefun " + SlimefunPlugin.getVersion());
SlimefunPlugin.logger().log(Level.WARNING, x, () -> "Failed to load " + chunks.getName() + " in World " + world.getName() + '(' + key + ") for Slimefun " + SlimefunPlugin.getVersion());
}
}
}
@ -245,7 +245,7 @@ public class BlockStorage {
inventories.put(l, new BlockMenu(preset, l, cfg));
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Error occurred while loading this Block Inventory: " + file.getName());
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Error occurred while loading this Block Inventory: " + file.getName());
}
}
}
@ -260,7 +260,7 @@ public class BlockStorage {
SlimefunPlugin.getRegistry().getUniversalInventories().put(preset.getID(), new UniversalBlockMenu(preset, cfg));
}
} catch (Exception x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Error occurred while loading this universal Inventory: " + file.getName());
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Error occurred while loading this universal Inventory: " + file.getName());
}
}
}
@ -291,7 +291,7 @@ public class BlockStorage {
return;
}
Slimefun.getLogger().log(Level.INFO, "Saving block data for world \"{0}\" ({1} change(s) queued)", new Object[] { world.getName(), changes });
SlimefunPlugin.logger().log(Level.INFO, "Saving block data for world \"{0}\" ({1} change(s) queued)", new Object[] { world.getName(), changes });
Map<String, Config> cache = new HashMap<>(blocksCache);
for (Map.Entry<String, Config> entry : cache.entrySet()) {
@ -305,7 +305,7 @@ public class BlockStorage {
try {
Files.delete(file.toPath());
} catch (IOException e) {
Slimefun.getLogger().log(Level.WARNING, e, () -> "Could not delete file \"" + file.getName() + '"');
SlimefunPlugin.logger().log(Level.WARNING, e, () -> "Could not delete file \"" + file.getName() + '"');
}
}
} else {
@ -315,7 +315,7 @@ public class BlockStorage {
try {
Files.move(tmpFile.toPath(), cfg.getFile().toPath(), StandardCopyOption.ATOMIC_MOVE);
} catch (IOException x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Error occurred while copying a temporary File for Slimefun " + SlimefunPlugin.getVersion());
SlimefunPlugin.logger().log(Level.SEVERE, x, () -> "An Error occurred while copying a temporary File for Slimefun " + SlimefunPlugin.getVersion());
}
}
}
@ -431,7 +431,7 @@ public class BlockStorage {
try {
return new BlockInfoConfig(parseJSON(json));
} catch (Exception x) {
Logger logger = Slimefun.getLogger();
Logger logger = SlimefunPlugin.logger();
logger.log(Level.WARNING, x.getClass().getName());
logger.log(Level.WARNING, "Failed to parse BlockInfo for Block @ {0}, {1}, {2}", new Object[] { l.getBlockX(), l.getBlockY(), l.getBlockZ() });
logger.log(Level.WARNING, json);
@ -457,7 +457,7 @@ public class BlockStorage {
writer.endObject();
return string.toString();
} catch (IOException x) {
Slimefun.getLogger().log(Level.SEVERE, "An error occurred while serializing BlockInfo", x);
SlimefunPlugin.logger().log(Level.SEVERE, "An error occurred while serializing BlockInfo", x);
return null;
}
}
@ -508,7 +508,7 @@ public class BlockStorage {
BlockStorage storage = getStorage(l.getWorld());
if (storage == null) {
Slimefun.getLogger().warning("Could not set Block info for non-registered World '" + l.getWorld().getName() + "'. Is some plugin trying to store data in a fake world?");
SlimefunPlugin.logger().warning("Could not set Block info for non-registered World '" + l.getWorld().getName() + "'. Is some plugin trying to store data in a fake world?");
return;
}
@ -817,7 +817,7 @@ public class BlockStorage {
return cfg;
} catch (Exception e) {
Slimefun.getLogger().log(Level.SEVERE, e, () -> "Failed to parse ChunkInfo for Slimefun " + SlimefunPlugin.getVersion());
SlimefunPlugin.logger().log(Level.SEVERE, e, () -> "Failed to parse ChunkInfo for Slimefun " + SlimefunPlugin.getVersion());
return emptyBlockData;
}
}

View File

@ -1,9 +1,6 @@
package me.mrCookieSlime.Slimefun.api;
import java.util.Optional;
import java.util.logging.Logger;
import javax.annotation.Nonnull;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@ -25,11 +22,6 @@ public final class Slimefun {
private Slimefun() {}
@Nonnull
public static Logger getLogger() {
return SlimefunPlugin.instance().getLogger();
}
/**
* Checks if this player can use this item.
*

View File

@ -10,7 +10,7 @@ import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.config.Config;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
// This class will be deprecated, relocated and rewritten in a future version.
public class BlockMenu extends DirtyChestMenu {
@ -118,7 +118,7 @@ public class BlockMenu extends DirtyChestMenu {
try {
Files.delete(file.toPath());
} catch (IOException e) {
Slimefun.getLogger().log(Level.WARNING, e, () -> "Could not delete file \"" + file.getName() + '"');
SlimefunPlugin.logger().log(Level.WARNING, e, () -> "Could not delete file \"" + file.getName() + '"');
}
}
}

View File

@ -20,7 +20,6 @@ options:
drop-excess-sf-give-items: false
guide:
default-view-book: false
show-vanilla-recipes: true
receive-on-first-join: true

View File

@ -4,7 +4,6 @@ commands:
cheat: Ermöglicht das Cheaten von Items
give: Gibt jemandem ein bestimmtes Item
guide: Gibt dir das Slimefun-Handbuch
timings: Zeigt einige Informationen über die Performance
teleporter: Erlaubt es dir Wegpunkte anderer Spieler anzusehen
versions: Eine Liste aller installierter Addons
search: Durchsucht dein Slimefun-Handbuch nach einem Begriff
@ -25,6 +24,11 @@ commands:
description: Lädt das Item in deiner Hand auf
charge-success: Dein Item wurde erfolgreich aufgeladen!
not-rechargeable: Dieses Item kann nicht aufgeladen werden!
timings:
description: Performance-Info für Slimefun und dessen Addons
please-wait: "&eEine Sekunde Geduld bitte... Die Ergebnisse werden aufbereitet!"
verbose-player: '&4Das "verbose" Argument kann nicht von Spielern verwendet werden.'
unknown-flag: "&4Unbekanntes Argument: &c%flag%"
guide:
search:
message: "&bWonach möchtest du suchen?"

View File

@ -3,7 +3,6 @@ commands:
cheat: Allows you to cheat Items
give: Give somebody some Slimefun Items
guide: Gives yourself a Slimefun Guide
timings: Lag-Info about your Server
teleporter: See other Player's Waypoints
versions: Lists all installed Addons
search: Searches your Guide for the given term
@ -27,6 +26,12 @@ commands:
charge-success: Item has been charged!
not-rechargeable: This item can not be charged!
timings:
description: Timings for Slimefun and its addon
please-wait: '&ePlease wait a second... The results are coming in!'
verbose-player: '&4The verbose flag cannot be used by a Player!'
unknown-flag: '&4Unknown flag: &c%flag%'
guide:
locked: 'LOCKED'
work-in-progress: 'This feature is not fully finished yet!'

View File

@ -4,7 +4,6 @@ commands:
cheat: Ezzel lekérhetsz tárgyakat
give: Slimefun tárgyak lekérése egy játékosnak
guide: Slimefun Útmutató lekérése
timings: Lag-információ a szerverről
teleporter: Játékosok útpontjainak megtekintése
versions: A kiegészítők listázása
search: Keresés egy kifejezésre az Útmutatóban
@ -24,6 +23,11 @@ commands:
description: Feltölti a kezedben lévő tárgyat
charge-success: Tárgy feltöltve!
not-rechargeable: Ez a tárgy nem tölthető fel!
timings:
description: Teljesítményinformáció a Slimefunról és a kiegészítőiről
please-wait: "&eKérjük várj... Érkeznek az eredmények!"
verbose-player: "&4A részletes megjelenítés flag nem használható játékosként!"
unknown-flag: "&4Ismeretlen flag: &c%flag%"
guide:
search:
message: "&bMire szeretnél keresni?"
@ -122,13 +126,13 @@ messages:
water: "&a&oA talizmánod megmentett a fulladástól"
angel: "&a&oA talizmánod megmentett a zuhanási sérüléstől"
fire: "&a&oA talizmánod megmentett a halálra elégéstől"
magician: "&a&oA talizmánod adott további fejlesztéseket is"
magician: "&a&oA talizmánod adott további varázslatokat is"
traveller: "&a&oA talizmánod gyors sebességet adott neked"
warrior: "&a&oA talizmánodtól növelte az erőd egy kis időre"
knight: "&a&oA talizmánod adott 5 másodpercre Regenerációt"
whirlwind: "&a&oA talizmánod visszavert egy lövedéket"
wizard: "&a&oA talizmánod erősítette a Szerencse enchantot, de néhány egyéb enchantot
gyengített"
wizard: "&a&oA talizmánod erősítette a Szerencse varázslatot, de néhány egyéb
varázslatot gyengített"
caveman: "&a&oA talizmánod adott Sietség effektet"
soulbound-rune:
fail: "&cEgyszerre csak egy tárgyat köthetsz a lelkedhez."
@ -151,24 +155,24 @@ messages:
- "&7Segítség, csapdába estem egy szerencsesüti gyárban!"
- "&7Holnap meghalsz... egy Creeper által"
- "&7Valamikor az életedben valami rossz fog történni!!!"
- "&7A következő héten észreveszed, hogy ez nem az igazi világ, hanem egy számítógépes
- "&7A jövő héten észreveszed, hogy ez nem az igazi világ, hanem egy számítógépes
játékban vagy"
- "&7Ez a süti néhány másodperc múlva jó ízű lesz"
- '&7Az utolsó szó, amelyet hallani fogsz: "KIÍRTANI!!!"'
- "&7Bármit is teszel, ne ölelj meg egy Creepert... Kipróbáltam. Jó érzés, de nem
éri meg."
- "&742. A válasz 42."
- "&7Walshy egy nap távol tartja a bajokat."
- "&7Minden nap egy Walshy távol tartja a bajokat."
- "&7Soha ne áss egyenesen!"
- "&7Ez csak egy kis karcolás!"
- "&7Mindig nézd az élet jó oldalát!"
- "&7Ez valójában keksz volt, és nem süti"
- "&7A neon táblák VILÁGÍTANAK!"
piglin-barter: "&4Slimefun tárgyakat nem cserélhetsz el piglinekkel."
piglin-barter: "&4Slimefun tárgyakat nem cserélhetsz el a piglinekkel."
enchantment-rune:
fail: "&cNem enchantolhatod ezt a tárgyat."
no-enchantment: "&cNem található megfelelő enchant ehhez az tárgyhoz."
success: "&aSikeresen alkalmaztál egy véletlenszerű enchantot erre a tárgyra."
fail: "&cNem varázsolhatod el ezt a tárgyat."
no-enchantment: "&cNem található megfelelő varázslat ehhez az tárgyhoz."
success: "&aSikeresen alkalmaztál egy véletlenszerű varázslatot erre a tárgyra."
tape-measure:
no-anchor: "&cBe kell állítanod egy kezdőpontot, mielőtt megkezdenéd a mérést!"
wrong-world: "&cA kezdőpont úgy tűnik, hogy egy másik világban van!"
@ -259,7 +263,7 @@ gps:
max: "&4Elérted a maximális útpontok számát"
duplicate: "&4Már létrehoztál egy ilyen nevű útpontot: &f%waypoint%"
insufficient-complexity:
- "&4Nem megfelelő a GPS-hálózat komplexitása: &c%complexity%"
- "&4Nem megfelelő a GPS-hálózat összetettsége: &c%complexity%"
- "&4a) Még nem telepítetted a GPS-hálózatot"
- "&4b) A GPS-hálózatod nem eléggé összetett"
geo:
@ -325,12 +329,11 @@ languages:
ru: Orosz
sk: Szlovák
zh-TW: Kínai (Tajvan)
vi: Vietnami
vi: Vietnámi
id: Indonéz
zh-CN: Kínai (Kína)
el: Görög
he: Héber
pt-BR: Portugál (Brazília)
ar: Arab
af: Afrikaans
da: Dán
@ -343,6 +346,7 @@ languages:
th: Thai
ro: Román
pt: Portugál (Portugália)
pt-BR: Portugál (Brazília)
bg: Bolgár
ko: Koreai
tr: Török

View File

@ -4,7 +4,6 @@ commands:
cheat: Slimefunガイドをチートモードで開く
give: 指定したプレイヤーにSlimefunアイテムを与える
guide: Slimefunガイドを取得
timings: サーバの負荷状況を表示
teleporter: 指定したプレイヤーのウェイポイントを表示
versions: バージョンについて
search: Slimefunガイド内を検索
@ -21,9 +20,14 @@ commands:
backpack-does-not-exist: "&4指定したバックパックは存在しません"
restored-backpack-given: "&aバックパックが返還されました"
charge:
description: 手に持っているアイテムを充電
charge-success: アイテム充電されました!
description: 手に持っているアイテムを充電する
charge-success: アイテム充電されました!
not-rechargeable: このアイテムは充電できません!
timings:
description: Slimefunに関連する負荷の計測
please-wait: "&e数秒お待ちください… 負荷の測定中です!"
verbose-player: "&4プレイヤーはverboseフラグを使用できません"
unknown-flag: "&4未知のフラグです: &c%flag%"
guide:
search:
message: "&b検索ワードをチャットで入力してください"
@ -314,7 +318,6 @@ languages:
el: ギリシャ語
he: ヘブライ語
pt: ポルトガル語(ポルトガル)
pt-BR: ポルトガル語(ブラジル)
ar: アラビア語
af: アフリカーンス語
da: デンマーク語
@ -326,6 +329,7 @@ languages:
fa: ペルシア語
th: タイ語
ro: ルーマニア語
pt-BR: ポルトガル語(ブラジル)
bg: ブルガリア語
ko: 韓国語
tr: トルコ語

View File

@ -1,214 +1,154 @@
---
android:
scripts:
already-uploaded: "&4Este script já foi enviado."
editor: Editor de Scripts
enter-name:
-
- "&eDigite um nome para o seu script"
instructions:
ATTACK_ANIMALS: "&4Atacar &c(Animais)"
ATTACK_ANIMALS_ADULT: "&4Atacar &c(Animais &7[Adultos]&c)"
ATTACK_MOBS: "&4Atacar &c(Mobs Hostis)"
ATTACK_MOBS_ANIMALS: "&4Atacar &c(Mobs Hostis & Animais)"
CATCH_FISH: "&bPegar Peixe"
CHOP_TREE: "&cCortar & Replantar"
DIG_DOWN: "&bCavar Para Baixo"
DIG_FORWARD: "&bCavar Para a Frente"
DIG_UP: "&bCavar Para Cima"
FARM_DOWN: "&bColheita e Replantio &7(Bloco abaixo)"
FARM_EXOTIC_DOWN: "&bColheita e Replantio Avançado &7(Bloco abaixo)"
FARM_EXOTIC_FORWARD: "&bColheita e Replantio Avançado"
FARM_FORWARD: "&bColheita e Replantio"
GO_DOWN: "&7Mover Para Baixo"
GO_FORWARD: "&7Mover Para Frente"
GO_UP: "&7Mover Para Cima"
INTERFACE_FUEL: "&cPuxe o combustível da interface voltada."
INTERFACE_ITEMS: "&9Envie o conteúdo do inventário para a interface exibida."
MOVE_AND_DIG_DOWN: "&bMover e Cavar Para Baixo"
MOVE_AND_DIG_FORWARD: "&bMover e Cavar Para a Frente"
MOVE_AND_DIG_UP: "&bMover & Cavar Para Cima"
REPEAT: "&9Repetir Script"
START: "&2Iniciar Script"
TURN_LEFT: "&7Virar à Esquerda"
TURN_RIGHT: "&7Virar à Direita"
WAIT: "&eAguarde 0.5s"
rating:
already: "&4Você já avaliou este script!"
own: "&4Você não pode avaliar seu próprio script!"
uploaded:
- "&bEnviando..."
- "&aO script foi enviado com sucesso!"
started: "&7Seu Android voltou a executar o script."
stopped: "&7Seu Android pausou o script."
anvil:
not-working: "&4Você não pode usar os itens do Slimefun em uma bigorna!"
backpack:
already-open: "&cEsta mochila já está aberta em outro lugar!"
no-stack: "&cVocê não pode empilhar mochilas!"
commands:
help: Exibe esta tela de ajuda
cheat: Permite que você "trapaceie" itens
give: Dá a alguém algum item do Slimefun
guide: Dá a si mesmo um Guia do Slimefun
help: Exibe esta tela de ajuda
timings: Lag-Info sobre o seu servidor
teleporter: Vê os Waypoints de outros jogadores
versions: Exibe todos os Add-ons instalados
search: Pesquisa no seu Guia o termo especificado
open_guide: Abre o guia do Slimefun sem usar o livro
stats: Mostra algumas estatísticas sobre um jogador
research:
description: Desbloqueia/Redefine pesquisas para um jogador
reset: "&cVocê redifiniu o Conhecimento de %player%"
reset-target: "&cSeu Conhecimento foi redefinido"
search: Pesquisa no seu Guia o termo especificado
stats: Mostra algumas estatísticas sobre um jogador
teleporter: Vê os Waypoints de outros jogadores
timings: Lag-Info sobre o seu servidor
versions: Exibe todos os Add-ons instalados
gps:
deathpoint: "&4Ponto de Morte &7%date%"
geo:
scan-required: "&4Scan Geográfico necessário! &cEscaneie esta chunk usando um
Scan Geográfico primeiro!"
insufficient-complexity:
- "&4Complexidade insuficiente da rede de GPS: &c%complexity%"
- "&4a) Você ainda não tem uma configuração de rede de GPS!"
- "&4b) Sua rede de GPS não é complexa o suficiente!"
waypoint:
added: "&aNovo WayPoint adicionado com sucesso."
max: "&4Você atingiu a quantidade máxima de WayPoints!"
new: "&eDigite o nome do WayPoint no bate-papo. &7(Códigos de cores suportados!)"
backpack:
description: Recuperar uma cópia de uma mochila existente
invalid-id: "&4O id deve ser um número não negativo!"
player-never-joined: Nenhum jogador com esse nome foi encontrado!
backpack-does-not-exist: "&4A mochila especificada não existe!"
restored-backpack-given: "&aSua mochila foi restaurada e foi adicionada ao seu
inventário!"
charge:
description: Carrega o item que você está segurando
charge-success: O item foi carregado!
not-rechargeable: Este item não pode ser carregado!
guide:
back:
guide: Voltar Para o Guia do Slimefun
settings: Voltar Para o Painel de Configurações
title: Voltar
cheat:
no-multiblocks: '&4Você não pode "trapacear" em Multiblocks, você precisa construí-los!'
credits:
commit: Comissão
commits: Comissões
profile-link: Clique aqui para visitar o perfil deles no GitHub
roles:
developer: "&6Desenvolvedor(a)"
resourcepack: "&cArtista de ResourcePack"
translator: "&9Tradutor(a)"
wiki: "&3Editor(a) da Wiki"
languages:
select: Clique aqui para selecionar este idioma
select-default: Clique aqui para selecionar o idioma padrão
selected-language: 'Idioma atual:'
translations:
lore: Clique aqui para adicionar seu próprio idioma
name: "&aHá algum idioma faltando?"
updated: "&aSeu idioma foi definido com sucesso para: &b%lang%"
pages:
next: Próxima Página
previous: Página Anterior
search:
message: "&bO que você gostaria de pesquisar?"
name: "&7Pesquisar..."
lore:
- "&bO que você gostaria de pesquisar?"
- "&7Digite seu termo de pesquisa no bate-papo."
message: "&bO que você gostaria de pesquisar?"
name: "&7Pesquisar..."
inventory: 'Procurando por: %item%'
tooltip: "&bClique para procurar um item"
cheat:
no-multiblocks: '&4Você não pode "trapacear" em Multiblocks, você precisa construí-los!'
languages:
updated: "&aSeu idioma foi definido com sucesso para: &b%lang%"
translations:
name: "&aHá algum idioma faltando?"
lore: Clique aqui para adicionar seu próprio idioma
select: Clique aqui para selecionar este idioma
select-default: Clique aqui para selecionar o idioma padrão
selected-language: 'Idioma atual:'
change: Clique para selecionar um novo idioma
description:
- "&7Agora você tem a opção de alterar"
- "&7o idioma no qual Slimefun"
- "&7será apresentado a você. Itens"
- "&7não podem ser traduzido por enquanto."
title:
addons: Add-ons do Slimefun4
bugs: Relatório de Erros
credits: Contribuidores do Slimefun4
languages: Selecione seu idioma preferido
main: Guia do Slimefun
settings: Config & Info
source: Código Fonte
languages: Selecione seu idioma preferido
credits: Contribuidores do Slimefun4
wiki: Wiki do Slimefun4
addons: Add-ons do Slimefun4
bugs: Relatório de Erros
source: Código Fonte
versions: Versões instaladas
credits:
commit: Comissão
commits: Comissões
roles:
developer: "&6Desenvolvedor(a)"
wiki: "&3Editor(a) da Wiki"
resourcepack: "&cArtista de ResourcePack"
translator: "&9Tradutor(a)"
profile-link: Clique aqui para visitar o perfil deles no GitHub
description:
- "&7Slimefun é um projeto de código aberto"
- "&7e mantido por uma grande comunidade de pessoas."
- "&7Mais de &e%contributors% &7pessoas trabalharam"
- "&7no Slimefun ao longo de todos esses anos."
open: Clique para ver nossos colaboradores
pages:
previous: Página Anterior
next: Próxima Página
tooltips:
open-category: Clique aqui para abrir
recipes:
generator: Tipos disponíveis de combustível
gold-pan: Recursos que você pode obter
machine: Receitas utilizadas nessa maquina
miner: Recursos que você pode obter com essa Mineradora
versions-notice: Isso é muito importante ao relatar erros!
wiki: Veja mais sobre esse item na Wiki oficial do Slimefun
inventory:
no-access: "&4Você não tem permissão para acessar este bloco."
languages:
af: Africano
ar: Árabe
cs: Tcheco
da: Dinamarquês
de: Alemão
default: Padrão do Servidor
el: Grego
en: Inglês
es: Espanhol
fa: Persa
fi: Finlandês
fr: Francês
he: Hebraico
hu: Húngaro
id: Indonésio
it: Italiano
ja: Japonês
lv: Letão
ms: Malaio
nl: Holandês
'no': Norueguês
pl: Polonês
pt: Português (Portugal)
pt-BR: Português (Brasil)
ro: Romena
ru: Russo
sk: Eslovaco
sv: Sueco
th: Tailandês
uk: Ucraniano
vi: Vietnamita
zh-CN: Chinês (China)
zh-TW: Chinês (Taiwan)
bg: Búlgaro
ko: Coreano
tr: Turco
machines:
ANCIENT_ALTAR:
not-enough-pedestals: "&4O altar não está rodeado pela quantidade necessária de
pedestais &c(%pedestals% de 8)&4."
unknown-catalyst: "&4Catalisador desconhecido! &cUse a receita correta."
unknown-recipe: "&4Receita desconhecida! &cUse a receita correta."
ANCIENT_PEDESTAL:
obstructed: "&4O pedestal está obstruído! &cRemova qualquer coisa acima do pedestal."
CARGO_NODES:
must-be-placed: "&4Deve ser colocado em um baú ou uma máquina!"
ELEVATOR:
click-to-teleport: "&eClique aqui &7para teleportar-se para o andar:"
current-floor: "&eEste é o andar em que você está atualmente:"
enter-name: "&7Digite o nome do andar no bate-papo. &r(Códigos de cores são suportados!)"
named: "&2Andar nomeado com sucesso para: &r%floor%"
no-destinations: "&4Nenhum destino encontrado!"
pick-a-floor: "&3- Escolha um andar -"
full-inventory: "&eDesculpe, meu inventário está muito cheio!"
GPS_CONTROL_PANEL:
title: GPS - Painel de Controle
transmitters: Informação de Transmissores
waypoints: Informação de Locais de Teleporte
HOLOGRAM_PROJECTOR:
enter-text: "&7Digite o nome do holograma no bate-papo. &r(Códigos de cores são
suportados!)"
inventory-title: Editor de Holograma
ignition-chamber-no-flint: "&cEstá faltando uma Pederneira na Câmara de Ignição."
in-use: "&cO inventário deste bloco está atualmente aberto por um jogador diferente."
pattern-not-found: "&eDesculpe, não pude reconhecer esta receita. Coloque os itens
no padrão correto no Ejetor."
TELEPORTER:
cancelled: "&4Teleporte cancelado!"
invulnerability: "&b&lVocê recebeu 30 segundos de invulnerabilidade!"
teleported: "&3Teleportado(a)!"
teleporting: "&3Teleportando-se..."
unknown-material: "&eDesculpe, não pude reconhecer o item no meu ejetor. Por favor,
coloque algo que eu sei."
wrong-item: "&eDesculpe, não pude reconhecer o item com o qual você clica com o
botão direito. Verifique as receitas e veja quais itens você pode usar."
recipes:
machine: Receitas utilizadas nessa maquina
miner: Recursos que você pode obter com essa Mineradora
generator: Tipos disponíveis de combustível
gold-pan: Recursos que você pode obter
climbing-pick: Superfícies que você pode escalar
back:
title: Voltar
guide: Voltar Para o Guia do Slimefun
settings: Voltar Para o Painel de Configurações
locked: BLOQUEADO
locked-category:
- Para desbloquear esta categoria, você
- precisa desbloquear todos os itens das
- seguintes categorias
work-in-progress: Este recurso não está totalmente concluído ainda!
messages:
cannot-place: "&cVocê não pode colocar esse bloco lá!"
diet-cookie: "&eVocê está começando a se sentir muito leve..."
not-researched: "&4Você não tem conhecimento suficiente para entender sobre isso."
not-enough-xp: "&4Você não tem XP suficiente para desbloquear isso!"
unlocked: '&bVocê desbloqueou &7"%research%"&b.'
only-players: "&4Este comando é apenas para jogadores"
unknown-player: "&4Jogador Desconhecido: &c%player%&4."
no-permission: "&4Você não tem a permissão necessária para fazer isso."
usage: "&4Uso: &c%usage%"
not-online: "&4%player% &cnão está online!"
given-item: '&bVocê deu &a%amount% &7"%item%&7"'
give-item: '&bVocê deu para %player% &a%amount% &7"%item%&7"'
give-research: '&bVocêu deu para %player% a Pesquisa &7"%research%&7"'
hungry: "&cVocê está com muita fome para fazer isso!"
disabled-in-world: "&4&lEste item foi desativado neste mundo."
disabled-item: "&4&lEste item foi desativado! Como você conseguiu isso?"
no-tome-yourself: "&cVocê não pode usar o &4Tomo do Conhecimento &cem si mesmo..."
multimeter: "&bEnergia Armazenada: &3%stored% &b/ &3%capacity%"
talisman:
anvil: "&a&oSeu Talismã salvou sua ferramenta de quebrar."
miner: "&a&oSeu talismã dobrou os drops."
hunter: "&a&oSeu talismã dobrou os minerios."
lava: "&a&oSeu talismã salvou você de queimar até a morte."
water: "&a&oSeu talismã salvou você de se afogar."
angel: "&a&oSeu talismã salvou você de sofrer dano de queda."
fire: "&a&oSeu talismã salvou você de queimar até a morte."
magician: "&a&oSeu talismã deu a você um encantamento adicional."
traveller: "&a&oSeu talismã deu a você um aumento de velocidade."
warrior: "&a&oSeu talismã melhorou sua força por um tempo."
knight: "&a&oSeu talismã lhe deu 5 segundos de regeneração."
whirlwind: "&a&oSeu talismã refletiu o projétil."
wizard: "&a&oSeu talismã deu a você um nível de Fortuna melhor, mas talvez tenha
diminuído alguns outros Níveis de Encantamento."
caveman: "&a&oSeu talismã te deu pressa"
soulbound-rune:
fail: "&cVocê pode vincular apenas um item à sua alma por vez."
success: "&aVocê vinculou com sucesso este item à sua alma! Você o manterá quando
morrer."
research:
start: "&7Os Espíritos Antigos sussurram palavras misteriosas no seu ouvido!"
progress: "&7Você começa a se perguntar sobre &b%research% &e(%progress%)"
fire-extinguish: "&7Você se extinguiu."
cannot-place: "&cVocê não pode colocar esse bloco lá!"
no-pvp: "&cVocê não pode lutar aqui!"
radiation: "&4Você foi exposto a uma radiação mortal! &cLivre-se do item radioativo
ou vista-se com um traje apropriado."
opening-guide: "&bAbrindo o guia, isso pode levar alguns segundos..."
opening-backpack: "&bAbrindo a mochila, isso pode levar alguns segundos..."
no-iron-golem-heal: "&cIsso não é uma barra de ferro. Você não pode usar isso para
curar Golens de Ferro!"
link-prompt: "&eClique aqui:"
diet-cookie: "&eVocê está começando a se sentir muito leve..."
fortune-cookie:
- "&7Ajude-me, estou preso em uma Fábrica de Biscoitos da Sorte!"
- "&7Você vai morrer amanhã... por um Creeper!"
@ -222,57 +162,208 @@ messages:
- "&742. A resposta é 42."
- "&7Um Walshy por dia manterá os problemas afastados."
- "&7Nunca cave para baixo!"
give-item: '&bVocê deu para %player% &a%amount% &7"%item%&7"'
given-item: '&bVocê deu &a%amount% &7"%item%&7"'
give-research: '&bVocêu deu para %player% a Pesquisa &7"%research%&7"'
hungry: "&cVocê está com muita fome para fazer isso!"
link-prompt: "&eClique aqui:"
mode-change: "&bO modo do dispositivo %device% foi alterado para: &9%mode%"
multimeter: "&bEnergia Armazenada: &3%stored% &b/ &3%capacity%"
no-iron-golem-heal: "&cIsso não é uma barra de ferro. Você não pode usar isso para
curar Golens de Ferro!"
no-permission: "&4Você não tem a permissão necessária para fazer isso."
no-pvp: "&cVocê não pode lutar aqui!"
not-enough-xp: "&4Você não tem XP suficiente para desbloquear isso!"
no-tome-yourself: "&cVocê não pode usar o &4Tomo do Conhecimento &cem si mesmo..."
not-online: "&4%player% &cnão está online!"
not-researched: "&4Você não tem conhecimento suficiente para entender sobre isso."
- "&7É apenas uma ferida de carne!"
- "&7Sempre olhe para o lado positivo da vida!"
- "&7Este foi realmente um bolacha e não um biscoito"
- "&7Os sinais de néon estão ILUMINADOS!"
invalid-item: "&4%item% &cnão é um item válido!"
invalid-amount: "&4%amount% &cnão é uma quantidade válida (precisa ser maior que
0)!"
invalid-item: "&4%item% &cnão é um item válido!"
invalid-research: "&4%research% &cnão é uma Pesquisa válida!"
only-players: "&4Este comando é apenas para jogadores"
opening-backpack: "&bAbrindo a mochila, isso pode levar alguns segundos..."
opening-guide: "&bAbrindo o guia, isso pode levar alguns segundos..."
radiation: "&4Você foi exposto a uma radiação mortal! &cLivre-se do item radioativo
ou vista-se com um traje apropriado."
research:
progress: "&7Você começa a se perguntar sobre &b%research% &e(%progress%)"
start: "&7Os Espíritos Antigos sussurram palavras misteriosas no seu ouvido!"
soulbound-rune:
fail: "&cVocê pode vincular apenas um item à sua alma por vez."
success: "&aVocê vinculou com sucesso este item à sua alma! Você o manterá quando
morrer."
talisman:
angel: "&a&oSeu talismã salvou você de sofrer dano de queda."
anvil: "&a&oSeu Talismã salvou sua ferramenta de quebrar."
fire: "&a&oSeu talismã salvou você de queimar até a morte."
hunter: "&a&oSeu talismã dobrou os minerios."
knight: "&a&oSeu talismã lhe deu 5 segundos de regeneração."
lava: "&a&oSeu talismã salvou você de queimar até a morte."
magician: "&a&oSeu talismã deu a você um encantamento adicional."
miner: "&a&oSeu talismã dobrou os drops."
traveller: "&a&oSeu talismã deu a você um aumento de velocidade."
warrior: "&a&oSeu talismã melhorou sua força por um tempo."
water: "&a&oSeu talismã salvou você de se afogar."
whirlwind: "&a&oSeu talismã refletiu o projétil."
wizard: "&a&oSeu talismã deu a você um nível de Fortuna melhor, mas talvez tenha
diminuído alguns outros Níveis de Encantamento."
unknown-player: "&4Jogador Desconhecido: &c%player%&4."
unlocked: '&bVocê desbloqueou &7"%research%"&b.'
usage: "&4Uso: &c%usage%"
miner:
no-ores: "&eDesculpe, não encontrei nenhum minério por perto!"
mode-change: "&bO modo do dispositivo %device% foi alterado para: &9%mode%"
tape-measure:
no-anchor: "&cVocê precisa definir uma âncora antes de começar a medir!"
wrong-world: "&cSua âncora parece estar em um mundo diferente!"
distance: "&7Medição realizada. \n&eDistância: %distance%"
anchor-set: "&aConfigurou a âncora com sucesso: &e%anchor%"
piglin-barter: "&4Você não pode negociar com piglins usando itens do Slimefun"
enchantment-rune:
fail: "&cVocê não pode encantar este item."
no-enchantment: "&cNão foi possível encontrar nenhum encantamento aplicável para
este item."
success: "&aVocê aplicou com sucesso um encantamento aplicável aleatório a este
item."
multi-tool:
mode-change: "&b%device% modo alterado para: &9%mode%"
not-shears: "&cA Multi Tool não pode ser usada como tesoura!"
climbing-pick:
dual-wielding: "&4Você precisa segurar as Escolhas de Escalada com as duas mãos
para usá-las!"
wrong-material: "&cVocê não pode escalar esta superfície. Verifique o seu Guia
do Slimefun para mais informações!"
bee-suit-slow-fall: "&eSuas Assas de Abelhas irão te ajudar a retornar ao chão em
segurança e lentamente"
machines:
pattern-not-found: "&eDesculpe, não pude reconhecer esta receita. Coloque os itens
no padrão correto no Ejetor."
unknown-material: "&eDesculpe, não pude reconhecer o item no meu ejetor. Por favor,
coloque algo que eu sei."
wrong-item: "&eDesculpe, não pude reconhecer o item com o qual você clica com o
botão direito. Verifique as receitas e veja quais itens você pode usar."
full-inventory: "&eDesculpe, meu inventário está muito cheio!"
in-use: "&cO inventário deste bloco está atualmente aberto por um jogador diferente."
ignition-chamber-no-flint: "&cEstá faltando uma Pederneira na Câmara de Ignição."
ANCIENT_ALTAR:
not-enough-pedestals: "&4O altar não está rodeado pela quantidade necessária de
pedestais &c(%pedestals% de 8)&4."
unknown-catalyst: "&4Catalisador desconhecido! &cUse a receita correta."
unknown-recipe: "&4Receita desconhecida! &cUse a receita correta."
ANCIENT_PEDESTAL:
obstructed: "&4O pedestal está obstruído! &cRemova qualquer coisa acima do pedestal."
HOLOGRAM_PROJECTOR:
enter-text: "&7Digite o nome do holograma no bate-papo. &r(Códigos de cores são
suportados!)"
inventory-title: Editor de Holograma
ELEVATOR:
no-destinations: "&4Nenhum destino encontrado!"
pick-a-floor: "&3- Escolha um andar -"
current-floor: "&eEste é o andar em que você está atualmente:"
click-to-teleport: "&eClique aqui &7para teleportar-se para o andar:"
enter-name: "&7Digite o nome do andar no bate-papo. &r(Códigos de cores são suportados!)"
named: "&2Andar nomeado com sucesso para: &r%floor%"
TELEPORTER:
teleporting: "&3Teleportando-se..."
teleported: "&3Teleportado(a)!"
cancelled: "&4Teleporte cancelado!"
invulnerability: "&b&lVocê recebeu 30 segundos de invulnerabilidade!"
gui:
title: Seus waypoints
tooltip: Clique para se teleportar
time: Tempo estimado
CARGO_NODES:
must-be-placed: "&4Deve ser colocado em um baú ou uma máquina!"
GPS_CONTROL_PANEL:
title: GPS - Painel de Controle
transmitters: Informação de Transmissores
waypoints: Informação de Locais de Teleporte
INDUSTRIAL_MINER:
finished: "&eSua Mineradora Industrial terminou! Obteve um total de %ores% minério
(s)!"
no-fuel: "&aSua mineradora industrial ficou sem combustível! Coloque seu combustível
no peito acima."
piston-facing: "&cSua Mineradora Industrial exige pistões para cima!"
piston-space: "&cOs dois pistões precisam ter um bloco vazio acima deles!"
destroyed: "&cO sua Mineradora industrial parece ter sido destruída."
already-running: "&cEsta Mineradora industrial já está em execução!"
full-chest: "&cO baú do sua Mineradora industrial está cheio!"
no-permission: "&4Você não parece ter permissão para operar uma Mineradora industrial
aqui!"
anvil:
not-working: "&4Você não pode usar os itens do Slimefun em uma bigorna!"
mcmmo-salvaging: "&4Você não pode reciclar itens do Slimefun!"
backpack:
already-open: "&cEsta mochila já está aberta em outro lugar!"
no-stack: "&cVocê não pode empilhar mochilas!"
workbench:
not-enhanced: "&4Você não pode usar itens do Slimefun em uma bancada de trabalho
normal."
gps:
deathpoint: "&4Ponto de Morte &7%date%"
waypoint:
new: "&eDigite o nome do WayPoint no bate-papo. &7(Códigos de cores suportados!)"
added: "&aNovo WayPoint adicionado com sucesso."
max: "&4Você atingiu a quantidade máxima de WayPoints!"
duplicate: "&4Você já criou um waypoint chamado: &f%waypoint%"
insufficient-complexity:
- "&4Complexidade insuficiente da rede de GPS: &c%complexity%"
- "&4a) Você ainda não tem uma configuração de rede de GPS!"
- "&4b) Sua rede de GPS não é complexa o suficiente!"
geo:
scan-required: "&4Scan Geográfico necessário! &cEscaneie esta chunk usando um
Scan Geográfico primeiro!"
inventory:
no-access: "&4Você não tem permissão para acessar este bloco."
android:
started: "&7Seu Android voltou a executar o script."
stopped: "&7Seu Android pausou o script."
scripts:
already-uploaded: "&4Este script já foi enviado."
instructions:
START: "&2Iniciar Script"
REPEAT: "&9Repetir Script"
WAIT: "&eAguarde 0.5s"
GO_FORWARD: "&7Mover Para Frente"
GO_UP: "&7Mover Para Cima"
GO_DOWN: "&7Mover Para Baixo"
TURN_LEFT: "&7Virar à Esquerda"
TURN_RIGHT: "&7Virar à Direita"
DIG_UP: "&bCavar Para Cima"
DIG_FORWARD: "&bCavar Para a Frente"
DIG_DOWN: "&bCavar Para Baixo"
MOVE_AND_DIG_UP: "&bMover & Cavar Para Cima"
MOVE_AND_DIG_FORWARD: "&bMover e Cavar Para a Frente"
MOVE_AND_DIG_DOWN: "&bMover e Cavar Para Baixo"
ATTACK_MOBS_ANIMALS: "&4Atacar &c(Mobs Hostis & Animais)"
ATTACK_MOBS: "&4Atacar &c(Mobs Hostis)"
ATTACK_ANIMALS: "&4Atacar &c(Animais)"
ATTACK_ANIMALS_ADULT: "&4Atacar &c(Animais &7[Adultos]&c)"
CHOP_TREE: "&cCortar & Replantar"
CATCH_FISH: "&bPegar Peixe"
FARM_FORWARD: "&bColheita e Replantio"
FARM_DOWN: "&bColheita e Replantio &7(Bloco abaixo)"
FARM_EXOTIC_FORWARD: "&bColheita e Replantio Avançado"
FARM_EXOTIC_DOWN: "&bColheita e Replantio Avançado &7(Bloco abaixo)"
INTERFACE_ITEMS: "&9Envie o conteúdo do inventário para a interface exibida."
INTERFACE_FUEL: "&cPuxe o combustível da interface voltada."
enter-name:
-
- "&eDigite um nome para o seu script"
uploaded:
- "&bEnviando..."
- "&aO script foi enviado com sucesso!"
rating:
own: "&4Você não pode avaliar seu próprio script!"
already: "&4Você já avaliou este script!"
editor: Editor de Scripts
languages:
default: Padrão do Servidor
en: Inglês
de: Alemão
fr: Francês
it: Italiano
es: Espanhol
pl: Polonês
sv: Sueco
nl: Holandês
cs: Tcheco
hu: Húngaro
lv: Letão
ru: Russo
sk: Eslovaco
zh-TW: Chinês (Taiwan)
vi: Vietnamita
id: Indonésio
zh-CN: Chinês (China)
el: Grego
he: Hebraico
ar: Árabe
af: Africano
da: Dinamarquês
fi: Finlandês
uk: Ucraniano
ms: Malaio
'no': Norueguês
ja: Japonês
fa: Persa
th: Tailandês
ro: Romena
pt: Português (Portugal)
pt-BR: Português (Brasil)
bg: Búlgaro
ko: Coreano
tr: Turco
hr: Croatian
mk: Macedonian
sr: Serbian
be: Belarusian
tl: Tagalog
miner:
no-ores: "&eDesculpe, não encontrei nenhum minério por perto!"
cauldron:
no-discoloring: "&4Você não pode descolorir uma Armadura do Slimefun"
cartography_table:
not-working: "&4Você não pode usar itens Slimefun em uma tabela de cartografia!"
brewing_stand:
not-working: "&4Você não pode usar itens Slimefun em um Suporte de poções!"
villagers:
no-trading: "&4Você não pode trocar itens Slimefun com os aldeões!"

View File

@ -1,250 +1,158 @@
---
android:
scripts:
already-uploaded: "&4Đoạn mã này đã được tải lên."
editor: Trình chỉnh sửa kịch bản
enter-name:
-
- "&eVui lòng nhập tên cho đoạn mã của bạn"
instructions:
ATTACK_ANIMALS: "&4Tấn công &c(Động vật)"
ATTACK_ANIMALS_ADULT: "&4Tấn công &c(Động vật &7[Trường thành]&c)"
ATTACK_MOBS: "&4Tấn công &c(Các mob hung dữ)"
ATTACK_MOBS_ANIMALS: "&4Tấn công &c(Mob và Động vật hung giữ)"
CATCH_FISH: "&bBắt cá"
CHOP_TREE: "&cChặt và trồng lại"
DIG_DOWN: "&bĐào xuống"
DIG_FORWARD: "&bĐào thẳng"
DIG_UP: "&bĐào lên"
FARM_DOWN: "&bThu hoạch và trồng lại &7(Khối bên dưới)"
FARM_EXOTIC_DOWN: "&bThu hoạch và thay thế nâng ca o&7(Khối ở dưới)"
FARM_EXOTIC_FORWARD: "&bThu hoạch và thay thế nâng cao"
FARM_FORWARD: "&bThu hoạch và trồng lại"
GO_DOWN: "&7Đi xuống"
GO_FORWARD: "&7Đi thẳng"
GO_UP: "&7Đi lên"
INTERFACE_FUEL: "&cKéo nhiên liệu từ giao diện"
INTERFACE_ITEMS: "&9Đẩy nội dung túi đồ lên giao diện"
MOVE_AND_DIG_DOWN: "&bDi chuyển và đào xuống"
MOVE_AND_DIG_FORWARD: "&bDi chuyển và đào thẳng"
MOVE_AND_DIG_UP: "&bDi chuyển và đào lên"
REPEAT: "&9Lặp lại Đoạn Mã"
START: "&2Bắt đầu chạy Đoạn Mã"
TURN_LEFT: "&7Rẽ trái"
TURN_RIGHT: "&7Rẽ phải"
WAIT: "&eĐợi 0.5s"
rating:
already: "&4Bạn đã để lại Xếp Hạng cho đoạn mã này!"
own: "&4Bạn không thể xếp hạng đoạn mã của chính mình!"
uploaded:
- "&bĐang tải lên..."
- "&aTải đoạn mã lên thành công!"
started: "&7Thiết bị Android của bạn đã tiếp tục chạy đoạn mã của nó"
stopped: "&7Thiết bị Android của bạn đã dùng chạy đoạn mã của nó"
anvil:
not-working: "&4Bạn không thể sử dụng vật phẩm Slimefun trên cái đê!"
backpack:
already-open: "&cXin lỗi, cái Ba lô này đã được mở ở một nơi nào khác!"
no-stack: "&cBạn không thể xếp nhiều Ba lô lại với nhau"
commands:
backpack:
backpack-does-not-exist: "&4Không tìm thấy ba lô đó!"
description: Lấy bản sao của một ba lô đã có sẵn
invalid-id: "&4ID phải là số nguyên dương!"
player-never-joined: "&4Không tìm thấy người chơi với tên như vậy!"
restored-backpack-given: "&aBa lô của bạn được khôi phục và được thêm vào túi
đồ của bạn!"
help: Hiển thị màn hình trợ giúp này
cheat: Cho phép bạn gian lận vật phẩm
give: Đưa cho ai đó vài món đồ Slimefun
guide: Cung cấp cho bạn một cuốn hướng dẫn Slimefun
help: Hiển thị màn hình trợ giúp này
timings: Thông tin Lag về máy chủ của bạn
teleporter: Xem các điểm dịch chuyển của người chơi khác
versions: Liệt kê tất cả các tiện ích mở rộng đã cài đặt
search: Tìm kiếm Hướng dẫn của bạn cho cụm từ đã cho
open_guide: Mở hướng dẫn của Slimefun mà không cần sử dụng sách
stats: Hiển thị một số thống kê về người chơi
research:
description: Mở khóa / Đặt lại nghiên cứu cho người chơi
reset: "&cBạn đã đặt lại Kiến thức của %player%"
reset-target: "&cKiến thức của bạn đã được đặt lại"
search: Tìm kiếm Hướng dẫn của bạn cho cụm từ đã cho
stats: Hiển thị một số thống kê về người chơi
teleporter: Xem các điểm dịch chuyển của người chơi khác
timings: Thông tin Lag về máy chủ của bạn
versions: Liệt kê tất cả các tiện ích mở rộng đã cài đặt
gps:
deathpoint: "&4Điểm chết &7%date%"
geo:
scan-required: "&4Yêu cầu Quét GEO! &cQuét chunk này bằng Máy Quét GEO trước!"
insufficient-complexity:
- "&4Độ phức tạp của mạng GPS không đủ: &c%complexity%"
- "&4a) Bạn chưa có thiết lập Mạng GPS"
- "&4b) Mạng GPS của bạn không đủ phức tạp"
waypoint:
added: "&aĐã thêm thành công một điểm tham chiếu mới"
max: "&4Bạn đã đạt đến số lượng điểm tham chiếu tối đa"
new: "&eVui lòng nhập tên cho điểm tham chiếu mới của bạn trên khung chat. &7(Mã
màu được hỗ trợ!)"
backpack:
description: Lấy bản sao của một ba lô đã có sẵn
invalid-id: "&4ID phải là số nguyên dương!"
player-never-joined: "&4Không tìm thấy người chơi với tên như vậy!"
backpack-does-not-exist: "&4Không tìm thấy ba lô đó!"
restored-backpack-given: "&aBa lô của bạn được khôi phục và được thêm vào túi
đồ của bạn!"
charge:
description: Sạc vật phẩm bạn đang cầm
charge-success: Vật phẩm này đã sạc xong!
not-rechargeable: Vật phẩm này không thể sạc được!
guide:
back:
guide: Quay trở lại Hướng dẫn Slimefun
settings: Quay trở lại Bảng Cài đặt
title: Quay lại
search:
message: "&bBạn muốn tìm kiếm cái gì?"
name: "&7Tìm kiếm..."
tooltip: "&bBấm để tìm vật phẩm"
inventory: 'Đang tìm: %item%'
lore:
- "&bBạn muốn tìm kiếm cái gì?"
- "&7Nhập cụm từ tìm kiếm của bạn vào khung chat"
cheat:
no-multiblocks: "&4Bạn không thể gian lận trong chế độ Đa khối, bạn phải xây dựng
chúng!"
credits:
commit: Commit
commits: Commits
profile-link: Nhấp để truy cập hồ sơ của họ trên GitHub
roles:
developer: "&6Nhà phát triển"
resourcepack: "&cNghệ sĩ gói tài nguyên"
translator: "&9Đóng góp bản dịch"
wiki: "&3Người chỉnh sửa Wiki"
languages:
updated: "&aNgôn ngữ của bạn đã được đặt thành công: &b%lang%"
translations:
name: "&aThiếu một cái gì đó?"
lore: Nhấn vào đây để thêm bản dịch của riêng bạn
select: Nhấn vào đây để chọn ngôn ngữ này
select-default: Nhấn vào đây để chọn ngôn ngữ mặc định
selected-language: 'Ngôn ngữ hiện đang chọn:'
translations:
lore: Nhấn vào đây để thêm bản dịch của riêng bạn
name: "&aThiếu một cái gì đó?"
updated: "&aNgôn ngữ của bạn đã được đặt thành công: &b%lang%"
change: Nhấp để chọn ngôn ngữ mới
description:
- "&7Bạn hiện có tùy chọn để thay đổi"
- "&7ngôn ngữ trong đó Slimefun"
- "&7sẽ được giới thiệu cho bạn. Vật phẩm"
- "& 7hiện không thể dịch được."
title:
main: Hướng dẫn sử dụng Slimefun
settings: Cài đặt và thông tin
languages: Chọn ngôn ngữ ưa thích của bạn
credits: Người đóng góp cho Slimefun4
wiki: Tài liệu Slimefun4
addons: Các bổ sung cho Slimefun4
bugs: Báo cáo lỗi
source: Mã nguồn
versions: Phiên bản đã cài
credits:
commit: Commit
commits: Commits
roles:
developer: "&6Nhà phát triển"
wiki: "&3Người chỉnh sửa Wiki"
resourcepack: "&cNghệ sĩ gói tài nguyên"
translator: "&9Đóng góp bản dịch"
profile-link: Nhấp để truy cập hồ sơ của họ trên GitHub
open: Nhấp để xem những người đóng góp của chúng tôi
description:
- "&7Slimefun là một dự án mã nguồn mở"
- "&7và được duy trì bởi một cộng đồng lớn."
- "&7Hơn &e%contributors% &7người đã làm việc"
- "&7Slimefun trong suốt những năm qua."
pages:
previous: Trang trước
next: Trang tiếp theo
tooltips:
open-category: Nhấn vào đây để mở
versions-notice: Đây là rất quan trọng khi báo cáo lỗi!
wiki: Xem vật phẩm này trên trang wiki chính thức của Slimefun
recipes:
machine: Các công thức được chế tạo ở máy này
miner: Tài nguyên bạn có thể kiếm được với máy đào này
generator: Các loại nguyên liệu có thể dùng
gold-pan: Tài nguyên bạn có thể kiếm được
climbing-pick: Những bề mặt bạn có thể leo lên
back:
title: Quay lại
guide: Quay trở lại Hướng dẫn Slimefun
settings: Quay trở lại Bảng Cài đặt
locked: ĐÃ KHÓA
locked-category:
- Để mở khóa danh mục này, bạn
- cần phải mở khóa các vật phẩm trong
- danh mục sau
pages:
next: Trang tiếp theo
previous: Trang trước
search:
inventory: 'Đang tìm: %item%'
lore:
- "&bBạn muốn tìm kiếm cái gì?"
- "&7Nhập cụm từ tìm kiếm của bạn vào khung chat"
message: "&bBạn muốn tìm kiếm cái gì?"
name: "&7Tìm kiếm..."
tooltip: "&bBấm để tìm vật phẩm"
title:
addons: Các bổ sung cho Slimefun4
bugs: Báo cáo lỗi
credits: Người đóng góp cho Slimefun4
languages: Chọn ngôn ngữ ưa thích của bạn
main: Hướng dẫn sử dụng Slimefun
settings: Cài đặt và thông tin
source: Mã nguồn
wiki: Tài liệu Slimefun4
tooltips:
open-category: Nhấn vào đây để mở
recipes:
generator: Các loại nguyên liệu có thể dùng
gold-pan: Tài nguyên bạn có thể kiếm được
machine: Các công thức được chế tạo ở máy này
miner: Tài nguyên bạn có thể kiếm được với máy đào này
versions-notice: Đây là rất quan trọng khi báo cáo lỗi!
wiki: Xem vật phẩm này trên trang wiki chính thức của Slimefun
inventory:
no-access: "&4Bạn không được phép truy cập vào khối này"
languages:
af: Tiếng Nam Phi
ar: Tiếng Ả Rập
be: Tiếng Bêlarut
bg: Tiếng Bulgaria
cs: Tiếng Séc
da: Tiếng Đan Mạch
de: Tiếng Đức
default: Máy chủ-Mặc định
el: Tiếng Hy Lạp
en: Tiếng Anh
es: Tiếng Tây Ban Nha
fa: Tiếng Ba Tư
fi: Tiếng Phần Lan
fr: Tiếng Pháp
he: Tiếng Do Thái
hr: Tiếng Croatia
hu: Tiếng Hungary
id: Tiếng Indonesia
it: Tiếng Ý
ja: Tiếng Nhật
ko: Tiếng Hàn
lv: Tiếng Latvia
ms: Tiếng Mã Lai
nl: Tiếng Hà Lan
'no': Tiếng Na Uy
pl: Tiếng Ba Lan
pt: Tiếng Bồ Đào Nha (Bồ Đào Nha)
pt-BR: Tiếng Bồ Đào Nha (Brazil)
ro: Tiếng Rumani
ru: Tiếng Nga
sk: Tiếng Slovak
sr: Tiếng Serbia
sv: Tiếng Thụy Điển
th: Tiếng Thái
tr: Tiếng Thổ Nhĩ Kỳ
uk: Tiếng Ukraina
vi: Tiếng Việt
zh-CN: Tiếng Trung (Trung Quốc)
zh-TW: Tiếng Trung Quốc (Đài Loan)
mk: Tiếng Macedonia
machines:
ANCIENT_ALTAR:
not-enough-pedestals: "&4Bàn thờ không được bao quanh bởi số lượng cần thiết của
các bệ &c(%pedestals% / 8)"
unknown-catalyst: "&4Không rõ Chất Xúc Tác! &cSử dụng đúng công thức thay thế!"
unknown-recipe: "&4Không rõ Công Thức! &cSử dụng đúng công thức thay thế!"
ANCIENT_PEDESTAL:
obstructed: "&4Bệ bị cản trở! &cLoại bỏ bất kì thứ gì trên bệ!"
CARGO_NODES:
must-be-placed: "&4Phải được đặt trên hòm hoặc máy!"
ELEVATOR:
click-to-teleport: "&eẤn &7để dịch chuyển đến tầng:"
current-floor: "&eĐây là tầng mà bạn hiện đang ở:"
enter-name: "&7Vui lòng nhập tên tầng mong muốn của bạn vào Khung trò chuyện.
&r(Mã màu được hỗ trợ)"
named: "&2Đặt tên thành công cho tầng này: &r%floor%"
no-destinations: "&4Không tìm thấy điểm đến"
pick-a-floor: "&4- Chọn một tầng -"
full-inventory: "&eXin lỗi, kho đồ của tôi đã quá đầy!"
GPS_CONTROL_PANEL:
title: GPS - Bảng điều khiển
transmitters: Tổng quan về các máy phát tín hiệu
waypoints: Tổng quan về các vị trí dịch chuyển
HOLOGRAM_PROJECTOR:
enter-text: "&7Vui lòng nhập Văn Bản Ba Chiều mong muốn của bạn vào Khung trò
chuyện. &r(Mã màu được hỗ trợ!)"
inventory-title: Trình chỉnh sửa ảnh ba chiều
ignition-chamber-no-flint: "&cIgnition Chamber đang thiếu Bật Lửa."
INDUSTRIAL_MINER:
already-running: "&cMáy đào công nghiệp này đang chạy!"
destroyed: "&cMáy đào công nghiệp của bạn có vẻ như bị phá hủy."
finished: "&eMáy đào công nghiệp của bạn đã chạy xong! Nó đã đào được %ores% khoáng
sản(s)!"
full-chest: "&cRương của máy đào công nghiệp đã đầy!"
no-fuel: "&cMáy đào công nghiệp của bạn hết nhiên liệu! Bỏ nhiên liệu vào rương
ở trên."
no-permission: "&4Có vẻ như bạn không có quyền để sử dụng máy đào ở đây!"
piston-facing: "&cMáy đào công nghiệp của bạn cần 2 pít-tông hướng lên trên!"
piston-space: "&cHai cái pít-tông cần hai khối không khí ở trên!"
in-use: "&cKhối trong túi đồ này hiện đang được mở bởi người chơi khác."
pattern-not-found: "&eXin lỗi, tôi không thể nhận ra Công Thức này. Vui lòng đặt
các vật phẩm với mẫu nhất định vào trong Máy Phân Phát."
TELEPORTER:
cancelled: "&4Dịch chuyển bị hủy bỏ!"
gui:
time: Thời gian dự kiến
title: Địa điểm của bạn
tooltip: Bấm để dịch chuyển
invulnerability: "&b&lBạn đã được cho 30 giây Bất Tử!"
teleported: "&3Đã dịch chuyển!"
teleporting: "&3Đang dịch chuyển..."
unknown-material: "&eXin lỗi, tôi không thể nhận ra vật phẩm trong máy phân phát.
Vui lòng đặt thứ gì đó trong đó mà tôi biết."
wrong-item: "&eXin lỗi, tôi không thể nhận ra vật phẩm mà bạn nhấp chuột phải vào
tôi. Kiểm tra Công Thức và xem những vật phẩm nào bạn có thể sử dụng."
work-in-progress: Tính năng này vẫn chưa hoàn thành!
messages:
cannot-place: "&cBạn không thể đặt khối ở đó!"
diet-cookie: "&eBạn đang bắt đầu cảm thấy rất nhẹ..."
not-researched: "&4Bạn không có đủ kiến thức để hiểu điều này"
not-enough-xp: "&4Bạn không có đủ kinh nghiệm để mở khóa"
unlocked: '&bBạn đã mở khóa &7"%research%"'
only-players: "&4Lệnh này chỉ dành cho người chơi"
unknown-player: "&4Người chơi chưa biết: &c%player%"
no-permission: "&4Bạn không có quyền để làm điều này"
usage: "&4Cách sử dụng: &c%usage%"
not-online: "&4%player% &cđang không trực tuyến!"
given-item: '&bBạn đã được nhận &a%amount% &7"%item%&7"'
give-item: '&bBạn đã gửi đến %player% &a%amount% &7"%item%&7"'
give-research: '&bBạn đã cho %player% nghiên cứu &7"%research%&7"'
hungry: "&cBạn quá đói để làm vậy!"
disabled-in-world: "&4&lVật phẩm này đã bị vô hiệu hóa ở thế giới này!"
disabled-item: "&4&lVật phẩm này đã bị vô hiệu hóa! Sao bạn có thể lấy được vật
phẩm đó?"
no-tome-yourself: "&cBạn không thể sử dụng &4Bộ kiến thức &ccho chính bạn..."
multimeter: "&bNăng lượng được tích trữ: &3%stored% &b/ &3%capacity%"
talisman:
anvil: "&a&oBùa hộ mệnh của bạn đã lưu công cụ của bạn khỏi bị phá vỡ"
miner: "&a&oBùa hộ mệnh của bạn vừa nhân đôi vật phẩm rớt"
hunter: "&a&oBùa hộ mệnh của bạn vừa nhân đôi vật phẩm rớt"
lava: "&a&oBùa hộ mệnh của bạn cứu bạn khỏi bị thiêu chết"
water: "&a&oBùa hộ mệnh của bạn vừa cứu bạn khỏi đuối nước"
angel: "&a&oBùa hộ mệnh của bạn vừa cứu bạn khỏi bị sát thương khi rơi"
fire: "&a&oBùa hộ mệnh của bạn cứu bạn khỏi bị thiêu chết"
magician: "&a&oBùa hộ mệnh của bạn cho bạn một phù phép bổ sung"
traveller: "&a&oBùa hộ mệnh của bạn cho bạn hiệu ứng Chạy Nhanh"
warrior: "&a&oBùa hộ mệnh của bạn đã cải thiện Sức mạnh của bạn trong một thời
gian"
knight: "&a&oBùa hộ mệnh của bạn đã cho bạn 5 giây hiệu ứng Hồi Máu"
whirlwind: "&a&oBùa hộ mệnhcủa bạn phản lại Phát Bắn"
wizard: "&a&oBùa hộ mệnh của bạn đã cho bạn một Cấp độ may mắn tốt hơn nhưng cũng
có thể hạ thấp một số Cấp độ phù phép khác"
caveman: "&a&oBùa ma thuật của bạn cho bạn hiệu ứng Đào nhanh"
soulbound-rune:
fail: "&cBạn chỉ có thể liên kết một vật phẩm với linh hồn của bạn trong cùng
một thời điểm."
success: "&aBạn đã liên kết thành công vật phẩm với linh hồn của bạn! Bạn sẽ giữ
vật phẩm khi chết."
research:
start: "&7Các Linh Hồn Cổ Đại nói thì thầm những từ ngữ bí ẩn vào tai bạn! "
progress: "&7Bạn bắt đầu thắc mắc về: &b%research% &e(%progress%)"
fire-extinguish: "&7Bạn đã tự dập tắt lửa chính bản thân"
cannot-place: "&cBạn không thể đặt khối ở đó!"
no-pvp: "&cBạn không thể đánh nhau ở đây!"
radiation: "&4Bạn đã tiếp xúc với bức xạ chết người! &cLoại bỏ vật phẩm phóng xạ
hoặc trang bị bộ đồ hazmat!"
opening-guide: "&bĐang mở hướng dẫn, việc này có thể mất một vài giây..."
opening-backpack: "&bĐang mở ba lô, việc này có thể mất một vài giây..."
no-iron-golem-heal: "&cĐây khỏi phải là Thỏi Sắt. Bạn không thể sử dụng thứ này
để hồi máu cho Người Khổng Lồ Sắt!"
link-prompt: "&eẤn vào đây:"
diet-cookie: "&eBạn đang bắt đầu cảm thấy rất nhẹ..."
fortune-cookie:
- "&7Cứu tôi, tôi bị bẫy trong một Nhà Máy Bánh Quy May Mắn"
- "&7Bạn sẽ chết vào ngày mai... bởi Creeper"
@ -258,58 +166,207 @@ messages:
- "&742. Câu trả lời là 42."
- "&7Một Walshy mỗi ngày sẽ giữ những rắc rối đi."
- "&7Không bao giờ đào thẳng xuống!"
give-item: '&bBạn đã gửi đến %player% &a%amount% &7"%item%&7"'
given-item: '&bBạn đã được nhận &a%amount% &7"%item%&7"'
give-research: '&bBạn đã cho %player% nghiên cứu &7"%research%&7"'
hungry: "&cBạn quá đói để làm vậy!"
link-prompt: "&eẤn vào đây:"
mode-change: "&b%device% đổi chế độ thành: &9%mode%"
multimeter: "&bNăng lượng được tích trữ: &3%stored% &b/ &3%capacity%"
no-iron-golem-heal: "&cĐây khỏi phải là Thỏi Sắt. Bạn không thể sử dụng thứ này
để hồi máu cho Người Khổng Lồ Sắt!"
no-permission: "&4Bạn không có quyền để làm điều này"
no-pvp: "&cBạn không thể đánh nhau ở đây!"
not-enough-xp: "&4Bạn không có đủ kinh nghiệm để mở khóa"
no-tome-yourself: "&cBạn không thể sử dụng &4Bộ kiến thức &ccho chính bạn..."
not-online: "&4%player% &cđang không trực tuyến!"
not-researched: "&4Bạn không có đủ kiến thức để hiểu điều này"
invalid-amount: "&4%amount% &ckhông hợp lệ : phải lớn hơn 0!"
- "&7Đó chỉ là một vết thương da thịt!"
- "&7Luôn nhìn theo hướng tích cực!"
- "&7 Cái này là bánh giòn chứ không phải bánh phồng"
- "&7Bảng đèn neon đẹp dữ!"
invalid-item: "&4%item% &ckhông phải là vật phẩm hợp lệ!"
invalid-amount: "&4%amount% &ckhông hợp lệ : phải lớn hơn 0!"
invalid-research: "&4%research% &ckhông phải là nghiên cứu hợp lệ!"
only-players: "&4Lệnh này chỉ dành cho người chơi"
opening-backpack: "&bĐang mở ba lô, việc này có thể mất một vài giây..."
opening-guide: "&bĐang mở hướng dẫn, việc này có thể mất một vài giây..."
radiation: "&4Bạn đã tiếp xúc với bức xạ chết người! &cLoại bỏ vật phẩm phóng xạ
hoặc trang bị bộ đồ hazmat!"
research:
progress: "&7Bạn bắt đầu thắc mắc về: &b%research% &e(%progress%)"
start: "&7Các Linh Hồn Cổ Đại nói thì thầm những từ ngữ bí ẩn vào tai bạn! "
soulbound-rune:
fail: "&cBạn chỉ có thể liên kết một vật phẩm với linh hồn của bạn trong cùng
một thời điểm."
success: "&aBạn đã liên kết thành công vật phẩm với linh hồn của bạn! Bạn sẽ giữ
vật phẩm khi chết."
talisman:
angel: "&a&oBùa hộ mệnh của bạn vừa cứu bạn khỏi bị sát thương khi rơi"
anvil: "&a&oBùa hộ mệnh của bạn đã lưu công cụ của bạn khỏi bị phá vỡ"
fire: "&a&oBùa hộ mệnh của bạn cứu bạn khỏi bị thiêu chết"
hunter: "&a&oBùa hộ mệnh của bạn vừa nhân đôi vật phẩm rớt"
knight: "&a&oBùa hộ mệnh của bạn đã cho bạn 5 giây hiệu ứng Hồi Máu"
lava: "&a&oBùa hộ mệnh của bạn cứu bạn khỏi bị thiêu chết"
magician: "&a&oBùa hộ mệnh của bạn cho bạn một phù phép bổ sung"
miner: "&a&oBùa hộ mệnh của bạn vừa nhân đôi vật phẩm rớt"
traveller: "&a&oBùa hộ mệnh của bạn cho bạn hiệu ứng Chạy Nhanh"
warrior: "&a&oBùa hộ mệnh của bạn đã cải thiện Sức mạnh của bạn trong một thời
gian"
water: "&a&oBùa hộ mệnh của bạn vừa cứu bạn khỏi đuối nước"
whirlwind: "&a&oBùa hộ mệnhcủa bạn phản lại Phát Bắn"
wizard: "&a&oBùa hộ mệnh của bạn đã cho bạn một Cấp độ may mắn tốt hơn nhưng cũng
có thể hạ thấp một số Cấp độ phù phép khác"
unknown-player: "&4Người chơi chưa biết: &c%player%"
unlocked: '&bBạn đã mở khóa &7"%research%"'
usage: "&4Cách sử dụng: &c%usage%"
miner:
no-ores: "&eXin lỗi, tôi không thể tìm bất kì Khoáng sản nào xung quanh!"
mode-change: "&b%device% đổi chế độ thành: &9%mode%"
piglin-barter: "&4Bạn không thể trao đổi với piglin bằng vật phẩm của Slimefun"
multi-tool:
mode-change: "&b%device% chế độ thay đổi thành: &9%mode%"
not-shears: "&cA Đa dụng cụ này không thể sử dụng như cái kéo!"
climbing-pick:
dual-wielding: "&4Bạn cần cầm Rìu leo ở cả 2 tay để dùng nó!"
wrong-material: "&cBạn không thể leo bề mặt này. Hãy xem hướng dẫn của Slimefun
để biết thêm!"
bee-suit-slow-fall: "&eCánh ong của bạn sẽ giúp bạn tiếp đất an toàn và chậm"
enchantment-rune:
fail: "&cBạn không thể phù phép vật phẩm này."
success: "&aBạn đã áp dụng thành công một loại phù phép ngẫu nhiên cho vật phẩm
này."
no-enchantment: "&cKhông thể tìm được bất kì loại phù phép nào phù hợp cho vật
phẩm"
tape-measure:
no-anchor: "&cBạn cần đặt neo trước khi có thể bắt đầu đo!"
wrong-world: "&cNeo của bạn dường như đang ở trong một thế giới khác!"
distance: |-
&7Đo lường được thực hiện.
&eKhoảng cách: %distance%
anchor-set: "&aĐặt thành công neo:&e%anchor%"
machines:
pattern-not-found: "&eXin lỗi, tôi không thể nhận ra Công Thức này. Vui lòng đặt
các vật phẩm với mẫu nhất định vào trong Máy Phân Phát."
unknown-material: "&eXin lỗi, tôi không thể nhận ra vật phẩm trong máy phân phát.
Vui lòng đặt thứ gì đó trong đó mà tôi biết."
wrong-item: "&eXin lỗi, tôi không thể nhận ra vật phẩm mà bạn nhấp chuột phải vào
tôi. Kiểm tra Công Thức và xem những vật phẩm nào bạn có thể sử dụng."
full-inventory: "&eXin lỗi, kho đồ của tôi đã quá đầy!"
in-use: "&cKhối trong túi đồ này hiện đang được mở bởi người chơi khác."
ignition-chamber-no-flint: "&cIgnition Chamber đang thiếu Bật Lửa."
ANCIENT_ALTAR:
not-enough-pedestals: "&4Bàn thờ không được bao quanh bởi số lượng cần thiết của
các bệ &c(%pedestals% / 8)"
unknown-catalyst: "&4Không rõ Chất Xúc Tác! &cSử dụng đúng công thức thay thế!"
unknown-recipe: "&4Không rõ Công Thức! &cSử dụng đúng công thức thay thế!"
ANCIENT_PEDESTAL:
obstructed: "&4Bệ bị cản trở! &cLoại bỏ bất kì thứ gì trên bệ!"
HOLOGRAM_PROJECTOR:
enter-text: "&7Vui lòng nhập Văn Bản Ba Chiều mong muốn của bạn vào Khung trò
chuyện. &r(Mã màu được hỗ trợ!)"
inventory-title: Trình chỉnh sửa ảnh ba chiều
ELEVATOR:
no-destinations: "&4Không tìm thấy điểm đến"
pick-a-floor: "&4- Chọn một tầng -"
current-floor: "&eĐây là tầng mà bạn hiện đang ở:"
click-to-teleport: "&eẤn &7để dịch chuyển đến tầng:"
enter-name: "&7Vui lòng nhập tên tầng mong muốn của bạn vào Khung trò chuyện.
&r(Mã màu được hỗ trợ)"
named: "&2Đặt tên thành công cho tầng này: &r%floor%"
TELEPORTER:
teleporting: "&3Đang dịch chuyển..."
teleported: "&3Đã dịch chuyển!"
cancelled: "&4Dịch chuyển bị hủy bỏ!"
invulnerability: "&b&lBạn đã được cho 30 giây Bất Tử!"
gui:
title: Địa điểm của bạn
tooltip: Bấm để dịch chuyển
time: Thời gian dự kiến
CARGO_NODES:
must-be-placed: "&4Phải được đặt trên hòm hoặc máy!"
GPS_CONTROL_PANEL:
title: GPS - Bảng điều khiển
transmitters: Tổng quan về các máy phát tín hiệu
waypoints: Tổng quan về các vị trí dịch chuyển
INDUSTRIAL_MINER:
no-fuel: "&cMáy đào công nghiệp của bạn hết nhiên liệu! Bỏ nhiên liệu vào rương
ở trên."
piston-facing: "&cMáy đào công nghiệp của bạn cần 2 pít-tông hướng lên trên!"
piston-space: "&cHai cái pít-tông cần hai khối không khí ở trên!"
destroyed: "&cMáy đào công nghiệp của bạn có vẻ như bị phá hủy."
already-running: "&cMáy đào công nghiệp này đang chạy!"
full-chest: "&cRương của máy đào công nghiệp đã đầy!"
no-permission: "&4Có vẻ như bạn không có quyền để sử dụng máy đào ở đây!"
finished: "&eMáy đào công nghiệp của bạn đã chạy xong! Nó đã đào được %ores% khoáng
sản(s)!"
anvil:
not-working: "&4Bạn không thể sử dụng vật phẩm Slimefun trên cái đê!"
mcmmo-salvaging: "&4Bạn không thể phục hồi giáp của Slimefun!"
backpack:
already-open: "&cXin lỗi, cái Ba lô này đã được mở ở một nơi nào khác!"
no-stack: "&cBạn không thể xếp nhiều Ba lô lại với nhau"
workbench:
not-enhanced: "&4Bạn không thể sử dụng vật phẩm Slimefun ở trên bàn làm việc thông
thường"
gps:
deathpoint: "&4Điểm chết &7%date%"
waypoint:
new: "&eVui lòng nhập tên cho điểm tham chiếu mới của bạn trên khung chat. &7(Mã
màu được hỗ trợ!)"
added: "&aĐã thêm thành công một điểm tham chiếu mới"
max: "&4Bạn đã đạt đến số lượng điểm tham chiếu tối đa"
duplicate: "&4Bạn từng tạo vị trí dịch chuyển tên: &f%waypoint% &4rồi"
insufficient-complexity:
- "&4Độ phức tạp của mạng GPS không đủ: &c%complexity%"
- "&4a) Bạn chưa có thiết lập Mạng GPS"
- "&4b) Mạng GPS của bạn không đủ phức tạp"
geo:
scan-required: "&4Yêu cầu Quét GEO! &cQuét chunk này bằng Máy Quét GEO trước!"
inventory:
no-access: "&4Bạn không được phép truy cập vào khối này"
android:
started: "&7Thiết bị Android của bạn đã tiếp tục chạy đoạn mã của nó"
stopped: "&7Thiết bị Android của bạn đã dùng chạy đoạn mã của nó"
scripts:
already-uploaded: "&4Đoạn mã này đã được tải lên."
instructions:
START: "&2Bắt đầu chạy Đoạn Mã"
REPEAT: "&9Lặp lại Đoạn Mã"
WAIT: "&eĐợi 0.5s"
GO_FORWARD: "&7Đi thẳng"
GO_UP: "&7Đi lên"
GO_DOWN: "&7Đi xuống"
TURN_LEFT: "&7Rẽ trái"
TURN_RIGHT: "&7Rẽ phải"
DIG_UP: "&bĐào lên"
DIG_FORWARD: "&bĐào thẳng"
DIG_DOWN: "&bĐào xuống"
MOVE_AND_DIG_UP: "&bDi chuyển và đào lên"
MOVE_AND_DIG_FORWARD: "&bDi chuyển và đào thẳng"
MOVE_AND_DIG_DOWN: "&bDi chuyển và đào xuống"
ATTACK_MOBS_ANIMALS: "&4Tấn công &c(Mob và Động vật hung giữ)"
ATTACK_MOBS: "&4Tấn công &c(Các mob hung dữ)"
ATTACK_ANIMALS: "&4Tấn công &c(Động vật)"
ATTACK_ANIMALS_ADULT: "&4Tấn công &c(Động vật &7[Trường thành]&c)"
CHOP_TREE: "&cChặt và trồng lại"
CATCH_FISH: "&bBắt cá"
FARM_FORWARD: "&bThu hoạch và trồng lại"
FARM_DOWN: "&bThu hoạch và trồng lại &7(Khối bên dưới)"
FARM_EXOTIC_FORWARD: "&bThu hoạch và thay thế nâng cao"
FARM_EXOTIC_DOWN: "&bThu hoạch và thay thế nâng ca o&7(Khối ở dưới)"
INTERFACE_ITEMS: "&9Đẩy nội dung túi đồ lên giao diện"
INTERFACE_FUEL: "&cKéo nhiên liệu từ giao diện"
enter-name:
-
- "&eVui lòng nhập tên cho đoạn mã của bạn"
uploaded:
- "&bĐang tải lên..."
- "&aTải đoạn mã lên thành công!"
rating:
own: "&4Bạn không thể xếp hạng đoạn mã của chính mình!"
already: "&4Bạn đã để lại Xếp Hạng cho đoạn mã này!"
editor: Trình chỉnh sửa kịch bản
languages:
default: Máy chủ-Mặc định
en: Tiếng Anh
de: Tiếng Đức
fr: Tiếng Pháp
it: Tiếng Ý
es: Tiếng Tây Ban Nha
pl: Tiếng Ba Lan
sv: Tiếng Thụy Điển
nl: Tiếng Hà Lan
cs: Tiếng Séc
hu: Tiếng Hungary
lv: Tiếng Latvia
ru: Tiếng Nga
sk: Tiếng Slovak
zh-TW: Tiếng Trung Quốc (Đài Loan)
vi: Tiếng Việt
id: Tiếng Indonesia
zh-CN: Tiếng Trung (Trung Quốc)
el: Tiếng Hy Lạp
he: Tiếng Do Thái
pt: Tiếng Bồ Đào Nha (Bồ Đào Nha)
pt-BR: Tiếng Bồ Đào Nha (Brazil)
ar: Tiếng Ả Rập
af: Tiếng Nam Phi
da: Tiếng Đan Mạch
fi: Tiếng Phần Lan
uk: Tiếng Ukraina
ms: Tiếng Mã Lai
'no': Tiếng Na Uy
ja: Tiếng Nhật
fa: Tiếng Ba Tư
th: Tiếng Thái
ro: Tiếng Rumani
bg: Tiếng Bulgaria
ko: Tiếng Hàn
tr: Tiếng Thổ Nhĩ Kỳ
hr: Tiếng Croatia
mk: Tiếng Macedonia
sr: Tiếng Serbia
be: Tiếng Bêlarut
tl: Tiếng Filipino
miner:
no-ores: "&eXin lỗi, tôi không thể tìm bất kì Khoáng sản nào xung quanh!"
villagers:
no-trading: "&4Bạn không thể trao đổi các vật phẩm Slimefun với dân làng!"
cartography_table:
not-working: "&4Bạn không thể sử dụng vật phẩm sủa Slimefun trong bàn sửa bản đồ"
cauldron:
no-discoloring: "&4Bạn không thể đổi màu giáp của Slimefun"
brewing_stand:
not-working: "&4Bạn không thể sử dụng các vật phẩm Slimefun trong quầy pha chế thuốc!"

View File

@ -2,17 +2,16 @@
commands:
help: 顯示此幫助畫面
cheat: 允許您以作弊取得物品
give: 給其他玩家Slimefun物品
guide: 給自己一個Slimefun指南
timings: 關於您的伺服器的卡頓信息
give: 給其他玩家 Slimefun 物品
guide: 給自己一個 Slimefun 指南
teleporter: 查看其他玩家的位置標點
versions: 列出所有已安裝的附屬插件
search: 在指南中搜索輸入的字句
open_guide: 打開Slimefun指南(不使用書本)
open_guide: 打開 Slimefun 指南(不使用書本)
stats: 顯示玩家的統計數據
research:
description: 解鎖/重置玩家的研究項目
reset: "&c你已使%player%變回笨蛋"
reset: "&c你已使 %player% 變回笨蛋"
reset-target: "&c你變回笨蛋了"
backpack:
description: 檢索已存在背包的副本
@ -24,6 +23,11 @@ commands:
description: 為你手中的物品充電
charge-success: 此物品已充電完成!
not-rechargeable: 此物品不可被充電!
timings:
description: Slimefun 及其附屬插件的耗能
please-wait: "&e請稍等⋯⋯結果快出來了"
verbose-player: "&4玩家不能使用「詳細資訊」標號"
unknown-flag: "&4未知標號&cflag"
guide:
search:
message: "&c你要搜尋什麼"
@ -50,10 +54,10 @@ guide:
- "&7不過科技物品礙於技術"
- "&7暫時沒有辦法翻譯"
title:
main: Slimefun指南
main: Slimefun 指南
settings: 設置及資訊
languages: 請選擇您偏好的語言
credits: Slimefun4貢獻者
credits: Slimefun4 貢獻者
wiki: Slimefun4 Wiki
addons: Slimefun4的附加插件
bugs: 錯誤報告
@ -100,15 +104,15 @@ guide:
messages:
not-researched: "&4你還沒有足夠的知識"
not-enough-xp: "&4你沒有足夠的經驗值來解鎖這個"
unlocked: "&b你已解鎖&7“%research%”"
unlocked: "&b你已解鎖 &7“%research%”"
only-players: "&4此命令只可由玩家發送"
unknown-player: "&4未知玩家&c%player%"
no-permission: "&4您沒有執行此動作所需的權限"
usage: "&4用法&c%usage%"
not-online: "&4%player% &c 還未上線!"
given-item: '&b你已獲得 &a%amount% &7"%item%&7"'
give-item: '&b你已給予%player% &a%amount% &7"%item%&7"'
give-research: '&b你已給予%player% 研究項目&7"%research%&7"'
give-item: '&b你已給予 %player% &a%amount% &7"%item%&7"'
give-research: '&b你已給予 %player% 研究項目&7"%research%&7"'
hungry: "&c你太餓了做不了這個"
disabled-in-world: "&4&l此物品在此世界中已被禁用"
disabled-item: "&4&l此物品已被禁用你到底是怎樣得到的"
@ -123,9 +127,9 @@ messages:
angel: "&a&o你的護符使你免疫摔落傷害"
fire: "&a&o你的護符將你從燒死邊緣中救回"
magician: "&a&o你的護符給了你額外的附魔"
traveller: "&a&o你的護符給了你速度3"
traveller: "&a&o你的護符給了你速度 3"
warrior: "&a&o你的護符暫時提高了你的力量"
knight: "&a&o你的護符給了你5秒的回復時間"
knight: "&a&o你的護符給了你 5 秒的回復時間"
whirlwind: "&a&o你的護符反射了投射物"
wizard: "&a&o你的護符為你升高了幸運等級但也降低了其他附魔等級"
caveman: "&a&o你的護符給了你挖掘加速效果"
@ -134,16 +138,16 @@ messages:
success: "&a您已成功將此物品綁定靈魂死後不會掉落。"
research:
start: "&7遠古之靈在你耳邊低語"
progress: "&7你開始研究&b%research% &e(%progress%)"
progress: "&7你開始研究 &b%research% &e(%progress%)"
fire-extinguish: "&7你熄滅了身上的火焰"
cannot-place: "&c不能在那裡放置方塊"
no-pvp: "&c這裡不准打架"
radiation: "&4你正暴露在致命的輻射之下&c立即丟棄放射性物品或裝備完整的防護服"
opening-guide: "&b正在打開指南這可能需要幾秒鐘的時間..."
opening-backpack: "&b正在打開背包這可能需要幾秒鐘的時間..."
no-iron-golem-heal: "&c這不是鐵錠。你不能用它來治鐵巨人!"
no-iron-golem-heal: "&c這不是鐵錠。你不能用它來治鐵巨人!"
link-prompt: "&e點擊此處"
diet-cookie: "&e你開始覺得很輕..."
diet-cookie: "&e你開始覺得很輕⋯⋯"
fortune-cookie:
- "&7快來幫幫我我被困在幸運餅乾工廠裡"
- "&7明天會有苦力怕歡樂送"
@ -153,7 +157,7 @@ messages:
- "&7你死前聽到的最後一句話會是「殲滅他」"
- "&7不要試著擁抱苦力怕...我試過,感覺還不錯,但是不值得。"
- "&742, 答案是 42。"
- "&7一天一Walshy煩惱遠離你。\n"
- "&7一天一 Walshy煩惱遠離你。\n"
- "&7永遠不要垂直往下挖"
- "&7這只是一個小傷"
- "&7永遠保持樂觀積極"
@ -177,7 +181,7 @@ messages:
wrong-material: "&c你無法攀爬這種平面。使用你的科技指南書以獲取更多資訊"
invalid-item: "&4%item% &c不存在"
invalid-amount: "&4%amount% &c不是有效數量數值必須大於 0"
invalid-research: "&4%research% &c不存在!"
invalid-research: "&4%research% &c不存在"
bee-suit-slow-fall: "&e你的蜂翅將會幫你緩慢且安全的回到地面"
mode-change: "&b%device% 模式切換至: &9%mode%"
machines:
@ -207,7 +211,7 @@ machines:
teleporting: "&3傳送中..."
teleported: "&3傳送成功"
cancelled: "&4傳送中止"
invulnerability: "&b&l你得到了30秒的無敵"
invulnerability: "&b&l你得到了 30 秒的無敵!"
gui:
title: 你的標記點
tooltip: 點擊以傳送
@ -243,9 +247,9 @@ gps:
max: "&4傳送點已達上限"
duplicate: "&4已經有叫作 &f%waypoint% &4的傳送點了"
insufficient-complexity:
- "&4GPS訊號不足:&c%complexity%"
- "&4a) GPS基礎設施未放置"
- "&4b) GPS訊號不足"
- "&4GPS 訊號不足:&c%complexity%"
- "&4a) GPS 基礎設施未放置"
- "&4b) GPS 訊號不足"
geo:
scan-required: "&4請先做地質掃描"
inventory:
@ -258,7 +262,7 @@ android:
instructions:
START: "&2執行程式"
REPEAT: "&9重複程式"
WAIT: "&e等0.5秒"
WAIT: "&e等0.5 秒"
GO_FORWARD: "&7向前移動"
GO_UP: "&7向上移動"
GO_DOWN: "&7向下移動"
@ -313,7 +317,7 @@ languages:
zh-CN: 中文(簡體)
el: 希臘語
he: 希伯來語
pt-BR: 葡萄牙文(巴西
pt: 葡萄牙文(葡萄牙
ar: 阿拉伯文
af: 南非語
da: 丹麥文
@ -325,7 +329,7 @@ languages:
fa: 波斯語
th: 泰語
ro: 羅馬尼亞語
pt: 葡萄牙文(葡萄牙
pt-BR: 葡萄牙文(巴西
bg: 保加利亞語
ko: 韓語
tr: 土耳其

View File

@ -118,6 +118,11 @@ slimefun:
lore:
- このアイテムの作成に使用する
- '機械: Refinery'
barter_drop:
name: ピグリンとの物々交換
lore:
- このアイテムは金インゴットを
- ピグリンとの物々交換で入手
minecraft:
shaped:
name: 定形レシピ

View File

@ -1,232 +1,250 @@
---
slimefun:
24k_gold_block: Thành phố Vàng
advanced_android: Android nâng cao
advanced_circuit_board: Bảng mạch tiên tiến
advanced_electric_smeltery: Lò rèn điện nâng cao
advanced_farmer_android: Android nâng cao - Nông phu
advanced_output_node: Nút đầu ra nâng cao
alloys: Hợp kim cao cấp
ancient_altar: Tế đài cổ đại
ancient_runes: Ngọc nguyên tố
android_interfaces: Giao diện Android
android_memory_core: Lõi máy móc
angel_talisman: Bùa hộ mệnh thiên sứ
animal_growth_accelerator: Máy tăng trưởng động vật
anvil_talisman: Bùa hộ mệnh của cái đe
armored_jetboots: Giày thép phản lực
armored_jetpack: Giáp phản lực
armor_forge: Bàn chế tạo giáp
auto_anvil: Đe tự động
auto_breeder: Máy cho ăn tự động
auto_drier: Một Ngày Khô ráo
auto_enchanting: Phù phép tự động
automated_crafting_chamber: Chế tạo tự động
automated_panning_machine: Sàng vàng Tự động
automatic_ignition_chamber: Máy đánh lửa tự động
backpacks: Ba lô
basic_circuit_board: Bảng mạch cơ bản
battery: Viên Pin đầu tiên của bạn
better_carbon_press: Máy ép carbon nâng cấp
better_crop_growth_accelerator: Máy tăng tưởng cây trồng nâng cấp
better_electric_crucibles: Máy nung đồ nóng
better_electric_furnace: Lò nung điện nâng cấp
better_food_fabricator: Máy chế tạo thực phẩm nâng cấp
better_freezer: Máy làm lạnh nâng cấp
better_gps_transmitters: Máy phát được nâng cấp
better_heated_pressure_chamber: Máy áp suất nâng cấp
better_solar_generators: Máy phát điện được nâng cấp
bio_reactor: Lò phản ứng sinh học
blade_of_vampires: Gươm ma cà rồng
blistering_ingots: Chất phóng xạ Blistering
block_placer: Máy đặt khối
boosted_uranium: Vòng tròn không kết thúc
boots_of_the_stomper: Giày cao cổ
bound_armor: Giáp linh hồn
bound_backpack: Balo Linh hồn
bound_tools: Dụng cụ linh hồn
bound_weapons: Vũ khí linh hồn
bronze: Tác phẩm đồng
cactus_armor: Bộ đồ xương rồng
capacitors: Tụ điện cấp 1
carbonado: Kim cương đen
carbonado_furnace: Lò nung cạnh carbon
carbonado_tools: Công cụ kim cương đen
carbon_press: Máy ép carbon
cargo_basics: Máy dịch chuyển đồ cơ bản
cargo_nodes: Thiết lập máy dịch chuyển đồ
charging_bench: Bàn sạc
coal_generator: Máy phát điện bằng than
cobalt_pickaxe: Cúp nhanh nhẹn
combustion_reactor: Lò phản ứng đốt cháy
common_talisman: Bùa hộ mệnh thông thường
composter: Khùng tổng hợp
compressor_and_carbon: Tác phẩm Carbon
cooler: Máy uống di động
copper_wire: Dây dẫn điện đồng
crop_growth_accelerator: Máy tăng trưởng cây trồng
crucible: Nồi nấu kim loại
crushed_ore: Máy nghiền quặng
damascus_steel: Thép Damascus
damascus_steel_armor: Giáp thép Damascus
diet_cookie: Bánh quy ăn kiêng
duct_tape: Băng dính
electric_crucible: Điện khí hóa
electric_furnaces: Lò nung điện
electric_ingot_machines: Máy chế tạo phôi điện
electric_motor: Động cơ điện
electric_ore_grinding: Máy nghiền điện
electric_press: Máy ép chạy bằng điện
electric_smeltery: Lò nung điện
elemental_staff: Trượng nguyên tố
elevator: Thang máy
elytra: Cánh cứng
ender_armor: Giáp Ender
ender_backpack: Balô Ender
ender_talismans: Bùa hộ mệnh Ender
energized_gps_transmitter: Máy phát cấp cao nhất
energized_solar_generator: Máy phát điện toàn thời gian
energy_regulator: Mạng năng lượng 101
enhanced_furnace: Lò nung cường hóa
essence_of_afterlife: Bột hậu kiếp
explosive_tools: Dụng cụ phát nổ
farmer_shoes: Giầy làm nông
fire_staff: Trượng Lửa
fire_talisman: Bùa hộ mệnh tránh lửa
first_aid: Bộ sơ cứu
flask_of_knowledge: Bình lưu trữ kinh nghiệm
fluid_pump: Máy bơm chất lỏng
fortune_cookie: Bánh quy may mắn
freezer: Máy làm lạnh
fuel: Nhiên liệu
geo_miner: Máy khai thác GEO
geo_scanner: Máy quét GEO
gilded_backpack: Ba lô mạ vàng
gilded_iron: Sắt mạ vàng
gilded_iron_armor: Giáp sắt mạ vàng
glowstone_armor: Giáp quang học
gold_armor: Bộ giáp sáng bóng
gold_carats: Vàng nguyên chất
golden_apple_juice: Thuốc vàng
gold_pan: Sàng vàng
gps_emergency_transmitter: Điểm khẩn cấp GPS
gps_setup: Máy thiết lập GPS cơ bản
grappling_hook: Cái Móc
grind_stone: Máy nghiền đá
hardened_glass: Kính cứng
hazmat_suit: Bộ đồ khử nhiễm
heated_pressure_chamber: Buồng gia nhiệt
hercules_pickaxe: Cúp Thần Hercules
high_tier_capacitors: Tụ điện cấp 2
high_tier_carbon_press: Máy ép cacbon tối thượng
high_tier_electric_ingot_machines: Máy chế tạo phôi điện siêu tốc
high_tier_enhanced_furnaces: Lò nung cao cấp
hologram_projector: Ảnh ba chiều
infernal_bonemeal: Phân bón âm phủ
infused_hopper: Phễu thu hút
infused_magnet: Nam châm truyền
jetboots: Giày phản lực
jetpacks: Giáp phản lực
juicer: Thức uống ngon
kelp_cookie: Tảo bẹ Ngon
knight_talisman: Bùa hộ mệnh kỵ sỹ
lava_crystal: Pha lê dung nham
lava_generator: Máy phát điện bằng dung nham
lava_talisman: Bùa hộ mệnh dung nham
lightning_rune: Ngọc của Sấm sét
lumber_axe: Búa đốn gỗ ( vjp )
lumps: Những cục bướu phép
magical_book_cover: Cuốn sách ma thuật liên kết
magic_eye_of_ender: Mắt Ender ma thuật
magician_talisman: Bùa hộ mệnh pháp sư
magic_sugar: Đường ma thuật
magic_workbench: Bài chế tạo-ma thuật
magnesium_generator: Sức mạnh từ Magiê
magnet: Nam Châm
misc_power_items: Vật phẩm quan trọng liên quan đến năng lượng
monster_jerky: Thịt quái quật khô
more_enhanced_furnaces: Lò nung tốt hơn
multimeter: Máy đo công suất điện
multitools: Đa công cụ
nether_gold_pan: Chảo vàng địa ngục
nether_ice: Đá địa ngục làm mát
nether_star_reactor: Lò hạt nhân sao địa ngục
nickel_and_cobalt: Nhiều quặng khác
night_vision_googles: Kính nhìn đêm
nuclear_reactor: Nhà máy điện hạt nhân
oil: Dầu
ore_crusher: Nhân đôi quặng
organic_fertilizer: Phân hữu cơ
organic_food: Thực phẩm hữu cơ
output_chest: Rương máy móc đưa ra cơ bản
pickaxe_of_containment: Cúp ngăn chặn
pickaxe_of_the_seeker: Cúp tìm kiếm
pickaxe_of_vein_mining: Cúp đào tĩnh mạch
plastic_sheet: Nhựa
walking_sticks: Gậy đi bộ
portable_crafter: Bàn chế tạo di động
fortune_cookie: Bánh quy may mắn
portable_dustbin: Thùng rác di động
pressure_chamber: Buồng áp suất
radiant_backpack: Ba lô phát quang
rainbow_blocks: Khối cầu vòng
reactor_access_port: Lò phản ứng được tiếp xúc
reactor_essentials: Lò phản ứng thiết yếu
redstone_alloy: Hợp kim Đá đỏ
reinforced_alloy: Hợp kim gia cố
reinforced_armor: Giáp gia cố
reinforced_furnace: Lò nung được gia cố
repaired_spawner: Lồng được sửa chữa
scroll_of_dimensional_teleposition: Cuộn giấy của sự xoay chuyển
seismic_axe: Rìu địa chấn
silicon: Thung lũng Silicon
meat_jerky: Thịt Khô
armor_forge: Bàn chế tạo giáp
glowstone_armor: Giáp quang học
lumps: Những cục bướu phép
ender_backpack: Balô Ender
ender_armor: Giáp Ender
magic_eye_of_ender: Mắt Ender ma thuật
magic_sugar: Đường ma thuật
monster_jerky: Thịt quái quật khô
slime_armor: Giáp chất nhờn
slimefun_metals: Kim loại mới
slime_steel_armor: Giáp thép trơ
smelters_pickaxe: Cúp nung
sword_of_beheading: Kiếm chặt đầu
basic_circuit_board: Bảng mạch cơ bản
advanced_circuit_board: Bảng mạch tiên tiến
smeltery: Lò đút
solar_generators: Máy sản xuất năng lượng mặt trời
solar_panel_and_helmet: Năng lượng mặt trời ( ngôi sao )
soulbound_rune: Ngọc linh hồn
special_bows: Cung đặc biệt
special_elytras: Cánh cứng đặc biệt
special_runes: Ngọc tím
steel: Thời đại thép
misc_power_items: Vật phẩm quan trọng liên quan đến năng lượng
battery: Viên Pin đầu tiên của bạn
steel_plate: Mạ thép
steel_thruster: Máy đẩy thép
storm_staff: Trượng Sét
sword_of_beheading: Kiếm chặt đầu
synthetic_diamond: Kim cương tổng hợp
synthetic_emerald: ngọc lục bảo tổng hợp
synthetic_sapphire: Ngọc bích tổng hợp
table_saw: Bàn cưa củi
teleporter: Thành phần cơ sở dịch chuyển
teleporter_activation_plates: Kích hoạt dịch chuyển tức thời
tome_of_knowledge_sharing: Bộ chia sẽ kiến thức
totem_of_undying: Vật tổ của sự Bất tử
trash_can: Rác
traveller_talisman: Bùa hộ mệnh du hành
uranium: Phóng xạ
walking_sticks: Gậy đi bộ
warrior_talisman: Bùa hộ mệnh chiến binh
water_staff: Trượng nước
water_talisman: Bùa hộ mệnh nước
whirlwind_talisman: Bùa hộ mệnh vòi rồng
wind_staff: Trượng gió
wither_assembler: Máy giết Wither tự động
wither_proof_glass: Kính chống Wither
wither_proof_obsidian: Hắc diện thạch chống Wither
wizard_talisman: Bùa hộ mệnh Thuật Sĩ
woven_backpack: Ba lô kết lại
xp_collector: Máy thu kinh nghiệm
meat_jerky: Thịt Khô
parachute: Dù bay
grappling_hook: Cái Móc
jetpacks: Giáp phản lực
multitools: Đa công cụ
solar_panel_and_helmet: Năng lượng mặt trời ( ngôi sao )
elemental_staff: Trượng nguyên tố
grind_stone: Máy nghiền đá
cactus_armor: Bộ đồ xương rồng
gold_pan: Sàng vàng
magical_book_cover: Cuốn sách ma thuật liên kết
slimefun_metals: Kim loại mới
ore_crusher: Nhân đôi quặng
bronze: Tác phẩm đồng
alloys: Hợp kim cao cấp
compressor_and_carbon: Tác phẩm Carbon
gilded_iron_armor: Giáp sắt mạ vàng
synthetic_diamond: Kim cương tổng hợp
pressure_chamber: Buồng áp suất
synthetic_sapphire: Ngọc bích tổng hợp
damascus_steel: Thép Damascus
damascus_steel_armor: Giáp thép Damascus
reinforced_alloy: Hợp kim gia cố
carbonado: Kim cương đen
magic_workbench: Bài chế tạo-ma thuật
wind_staff: Trượng gió
reinforced_armor: Giáp gia cố
ore_washer: Máy rửa quặng
gold_carats: Vàng nguyên chất
silicon: Thung lũng Silicon
fire_staff: Trượng Lửa
smelters_pickaxe: Cúp nung
common_talisman: Bùa hộ mệnh thông thường
anvil_talisman: Bùa hộ mệnh của cái đe
miner_talisman: Bùa hộ mệnh của thợ mỏ
hunter_talisman: Bùa hộ mệnh của thợ săn
lava_talisman: Bùa hộ mệnh dung nham
water_talisman: Bùa hộ mệnh nước
angel_talisman: Bùa hộ mệnh thiên sứ
fire_talisman: Bùa hộ mệnh tránh lửa
lava_crystal: Pha lê dung nham
magician_talisman: Bùa hộ mệnh pháp sư
traveller_talisman: Bùa hộ mệnh du hành
warrior_talisman: Bùa hộ mệnh chiến binh
knight_talisman: Bùa hộ mệnh kỵ sỹ
gilded_iron: Sắt mạ vàng
synthetic_emerald: ngọc lục bảo tổng hợp
chainmail_armor: Giáp lưới
whirlwind_talisman: Bùa hộ mệnh vòi rồng
wizard_talisman: Bùa hộ mệnh Thuật Sĩ
lumber_axe: Búa đốn gỗ ( vjp )
hazmat_suit: Bộ đồ khử nhiễm
uranium: Phóng xạ
crushed_ore: Máy nghiền quặng
redstone_alloy: Hợp kim Đá đỏ
carbonado_tools: Công cụ kim cương đen
first_aid: Bộ sơ cứu
gold_armor: Bộ giáp sáng bóng
night_vision_googles: Kính nhìn đêm
pickaxe_of_containment: Cúp ngăn chặn
hercules_pickaxe: Cúp Thần Hercules
table_saw: Bàn cưa củi
slime_steel_armor: Giáp thép trơ
blade_of_vampires: Gươm ma cà rồng
water_staff: Trượng nước
24k_gold_block: Thành phố Vàng
composter: Khùng tổng hợp
farmer_shoes: Giầy làm nông
explosive_tools: Dụng cụ phát nổ
automated_panning_machine: Sàng vàng Tự động
boots_of_the_stomper: Giày cao cổ
pickaxe_of_the_seeker: Cúp tìm kiếm
backpacks: Ba lô
woven_backpack: Ba lô kết lại
crucible: Nồi nấu kim loại
gilded_backpack: Ba lô mạ vàng
armored_jetpack: Giáp phản lực
ender_talismans: Bùa hộ mệnh Ender
nickel_and_cobalt: Nhiều quặng khác
magnet: Nam Châm
infused_magnet: Nam châm truyền
cobalt_pickaxe: Cúp nhanh nhẹn
essence_of_afterlife: Bột hậu kiếp
bound_backpack: Balo Linh hồn
jetboots: Giày phản lực
armored_jetboots: Giày thép phản lực
seismic_axe: Rìu địa chấn
pickaxe_of_vein_mining: Cúp đào tĩnh mạch
bound_weapons: Vũ khí linh hồn
bound_tools: Dụng cụ linh hồn
bound_armor: Giáp linh hồn
juicer: Thức uống ngon
repaired_spawner: Lồng được sửa chữa
enhanced_furnace: Lò nung cường hóa
more_enhanced_furnaces: Lò nung tốt hơn
high_tier_enhanced_furnaces: Lò nung cao cấp
reinforced_furnace: Lò nung được gia cố
carbonado_furnace: Lò nung cạnh carbon
electric_motor: Động cơ điện
block_placer: Máy đặt khối
scroll_of_dimensional_teleposition: Cuộn giấy của sự xoay chuyển
special_bows: Cung đặc biệt
tome_of_knowledge_sharing: Bộ chia sẽ kiến thức
flask_of_knowledge: Bình lưu trữ kinh nghiệm
hardened_glass: Kính cứng
golden_apple_juice: Thuốc vàng
cooler: Máy uống di động
ancient_altar: Tế đài cổ đại
wither_proof_obsidian: Hắc diện thạch chống Wither
ancient_runes: Ngọc nguyên tố
special_runes: Ngọc tím
infernal_bonemeal: Phân bón âm phủ
rainbow_blocks: Khối cầu vòng
infused_hopper: Phễu thu hút
wither_proof_glass: Kính chống Wither
duct_tape: Băng dính
plastic_sheet: Nhựa
android_memory_core: Lõi máy móc
oil: Dầu
fuel: Nhiên liệu
hologram_projector: Ảnh ba chiều
capacitors: Tụ điện cấp 1
high_tier_capacitors: Tụ điện cấp 2
solar_generators: Máy sản xuất năng lượng mặt trời
electric_furnaces: Lò nung điện
electric_ore_grinding: Máy nghiền điện
heated_pressure_chamber: Buồng gia nhiệt
coal_generator: Máy phát điện bằng than
bio_reactor: Lò phản ứng sinh học
auto_enchanting: Phù phép tự động
auto_anvil: Đe tự động
multimeter: Máy đo công suất điện
gps_setup: Máy thiết lập GPS cơ bản
gps_emergency_transmitter: Điểm khẩn cấp GPS
programmable_androids: Android lập trình được
android_interfaces: Giao diện Android
geo_scanner: Máy quét GEO
combustion_reactor: Lò phản ứng đốt cháy
teleporter: Thành phần cơ sở dịch chuyển
teleporter_activation_plates: Kích hoạt dịch chuyển tức thời
better_solar_generators: Máy phát điện được nâng cấp
better_gps_transmitters: Máy phát được nâng cấp
elevator: Thang máy
energized_solar_generator: Máy phát điện toàn thời gian
energized_gps_transmitter: Máy phát cấp cao nhất
energy_regulator: Mạng năng lượng 101
butcher_androids: Android đồ tể
organic_food: Thực phẩm hữu cơ
auto_breeder: Máy cho ăn tự động
advanced_android: Android nâng cao
advanced_butcher_android: Android nâng cao - Đồ tể
advanced_fisherman_android: Android nâng cao - Câu cá
animal_growth_accelerator: Máy tăng trưởng động vật
xp_collector: Máy thu kinh nghiệm
organic_fertilizer: Phân hữu cơ
crop_growth_accelerator: Máy tăng trưởng cây trồng
better_crop_growth_accelerator: Máy tăng tưởng cây trồng nâng cấp
reactor_essentials: Lò phản ứng thiết yếu
nuclear_reactor: Nhà máy điện hạt nhân
freezer: Máy làm lạnh
cargo_basics: Máy dịch chuyển đồ cơ bản
cargo_nodes: Thiết lập máy dịch chuyển đồ
electric_ingot_machines: Máy chế tạo phôi điện
high_tier_electric_ingot_machines: Máy chế tạo phôi điện siêu tốc
automated_crafting_chamber: Chế tạo tự động
better_food_fabricator: Máy chế tạo thực phẩm nâng cấp
reactor_access_port: Lò phản ứng được tiếp xúc
fluid_pump: Máy bơm chất lỏng
better_freezer: Máy làm lạnh nâng cấp
boosted_uranium: Vòng tròn không kết thúc
trash_can: Rác
advanced_output_node: Nút đầu ra nâng cao
carbon_press: Máy ép carbon
electric_smeltery: Lò nung điện
better_electric_furnace: Lò nung điện nâng cấp
better_carbon_press: Máy ép carbon nâng cấp
empowered_android: Android siêu cấp
empowered_butcher_android: Android siêu cấp - Đồ tể
empowered_fisherman_android: Android siêu cấp - Câu cá
high_tier_carbon_press: Máy ép cacbon tối thượng
wither_assembler: Máy giết Wither tự động
better_heated_pressure_chamber: Máy áp suất nâng cấp
elytra: Cánh cứng
special_elytras: Cánh cứng đặc biệt
electric_crucible: Điện khí hóa
better_electric_crucibles: Máy nung đồ nóng
advanced_electric_smeltery: Lò rèn điện nâng cao
advanced_farmer_android: Android nâng cao - Nông phu
lava_generator: Máy phát điện bằng dung nham
nether_ice: Đá địa ngục làm mát
nether_star_reactor: Lò hạt nhân sao địa ngục
blistering_ingots: Chất phóng xạ Blistering
automatic_ignition_chamber: Máy đánh lửa tự động
output_chest: Rương máy móc đưa ra cơ bản
copper_wire: Dây dẫn điện đồng
radiant_backpack: Ba lô phát quang
auto_drier: Một Ngày Khô ráo
diet_cookie: Bánh quy ăn kiêng
storm_staff: Trượng Sét
soulbound_rune: Ngọc linh hồn
geo_miner: Máy khai thác GEO
lightning_rune: Ngọc của Sấm sét
totem_of_undying: Vật tổ của sự Bất tử
charging_bench: Bàn sạc
nether_gold_pan: Chảo vàng địa ngục
electric_press: Máy ép chạy bằng điện
magnesium_generator: Sức mạnh từ Magiê
kelp_cookie: Tảo bẹ Ngon
makeshift_smeltery: Lò rèn cải tiến
tree_growth_accelerator: Cây lớn nhanh hơn
industrial_miner: Máy đào công nghiệp
advanced_industrial_miner: Đào tốt hơn
magical_zombie_pills: Thuốc kháng khuẩn thây ma
auto_brewer: Lò thuốc công nghiệp
enchantment_rune: Đá cường hoá cổ
lead_clothing: Vải pha chì
tape_measure: Thước dây
iron_golem_assembler: Máy lắp Golem Sắt
climbing_pick: Móc kéo
shulker_shell: Shulker tổng hợp
villager_rune: Đá trao đổi
caveman_talisman: Bùa thổ dân
even_higher_tier_capacitors: Pin cấp 3
elytra_cap: Mũ lượn
energy_connectors: Đầu nối
bee_armor: Giáp ong

View File

@ -12,13 +12,13 @@ resources:
salt:
uranium: Uránium
slimefunorechunks:
iron_ore_chunk: Vasérc chunk
gold_ore_chunk: Aranyérc chunk
copper_ore_chunk: Rézérc chunk
tin_ore_chunk: Ónérc chunk
silver_ore_chunk: Ezüstérc chunk
aluminum_ore_chunk: Alumíniumérc chunk
lead_ore_chunk: Ólomérc chunk
zinc_ore_chunk: Cinkérc chunk
nickel_ore_chunk: Nikkelérc chunk
cobalt_ore_chunk: Kobaltérc Chunk
iron_ore_chunk: Vasérctömb
gold_ore_chunk: Aranyérc-tömb
copper_ore_chunk: Rézérctömb
tin_ore_chunk: Ónérctömb
silver_ore_chunk: Ezüstérctömb
aluminum_ore_chunk: Alumíniumérc-tömb
lead_ore_chunk: Ólomérctömb
zinc_ore_chunk: Cinkérctömb
nickel_ore_chunk: Nikkelérctömb
cobalt_ore_chunk: Kobaltérctömb

View File

@ -0,0 +1,24 @@
---
tooltips:
results: Resultados de Geo-Scan
chunk: Pedaço Escaneado
world: Mundo
unit: Unidade
units: Unidades
resources:
slimefun:
oil: Óleo
nether_ice: Gelo do Nether
salt: Sal
uranium: 'Urânio '
slimefunorechunks:
iron_ore_chunk: Pedaço de Minério de Ferro
gold_ore_chunk: Pedaço de Minério de Ouro
copper_ore_chunk: Pedaço de Minério de Cobre
tin_ore_chunk: Pedaço de Minério de Estanho
silver_ore_chunk: Pedaço de Minério de Prata
aluminum_ore_chunk: Pedaço de Minério de Alumínio
lead_ore_chunk: Pedaço de Minério de Chumbo
zinc_ore_chunk: Pedaço de Minério de Zinco
nickel_ore_chunk: Pedaço de Minério de Níquel
cobalt_ore_chunk: Pedaço de Minério de Cobalto

View File

@ -23,7 +23,6 @@ softdepend:
# We hook into these plugins too, but they depend on Slimefun.
loadBefore:
- ChestTerminal
- ExoticGarden
# Our commands
commands:

View File

@ -12,7 +12,7 @@ import org.junit.jupiter.params.provider.ValueSource;
import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.ServerMock;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
@ -39,7 +39,7 @@ class TestGuideCommand {
player.setOp(op);
server.execute("slimefun", player, "guide").assertSucceeded();
ItemStack guide = SlimefunGuide.getItem(SlimefunGuideLayout.CHEST);
ItemStack guide = SlimefunGuide.getItem(SlimefunGuideMode.SURVIVAL_MODE);
Assertions.assertEquals(op, SlimefunUtils.containsSimilarItem(player.getInventory(), guide, true));
}
}

View File

@ -1,36 +0,0 @@
package io.github.thebusybiscuit.slimefun4.testing.tests.guide;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide;
class TestBookSlimefunGuide {
@BeforeAll
public static void load() {
MockBukkit.mock();
MockBukkit.load(SlimefunPlugin.class);
}
@AfterAll
public static void unload() {
MockBukkit.unmock();
}
@Test
@DisplayName("Test Getters for Chest Slimefun Guide")
void testBasicGetters() {
BookSlimefunGuide guide = new BookSlimefunGuide();
Assertions.assertEquals(SlimefunGuideLayout.BOOK, guide.getLayout());
Assertions.assertTrue(guide.isSurvivalMode());
}
}

View File

@ -1,36 +0,0 @@
package io.github.thebusybiscuit.slimefun4.testing.tests.guide;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.ChestSlimefunGuide;
class TestChestSlimefunGuide {
@BeforeAll
public static void load() {
MockBukkit.mock();
MockBukkit.load(SlimefunPlugin.class);
}
@AfterAll
public static void unload() {
MockBukkit.unmock();
}
@Test
@DisplayName("Test Getters for Chest Slimefun Guide")
void testBasicGetters() {
ChestSlimefunGuide guide = new ChestSlimefunGuide(false);
Assertions.assertEquals(SlimefunGuideLayout.CHEST, guide.getLayout());
Assertions.assertTrue(guide.isSurvivalMode());
}
}

View File

@ -22,7 +22,7 @@ import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.ServerMock;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.VanillaItem;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.crafting.GrindstoneListener;
@ -82,8 +82,8 @@ public class TestGrindstoneListener {
}
@ParameterizedTest
@EnumSource(SlimefunGuideLayout.class)
public void testGrindStoneWithSlimefunGuide(SlimefunGuideLayout layout) {
@EnumSource(SlimefunGuideMode.class)
public void testGrindStoneWithSlimefunGuide(SlimefunGuideMode layout) {
InventoryClickEvent event = mockGrindStoneEvent(SlimefunGuide.getItem(layout));
Assertions.assertEquals(Result.DENY, event.getResult());
}

View File

@ -10,6 +10,7 @@ import org.bukkit.inventory.ItemStack;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import be.seeseemelk.mockbukkit.MockBukkit;
@ -19,7 +20,7 @@ import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory;
import io.github.thebusybiscuit.slimefun4.core.categories.LockedCategory;
import io.github.thebusybiscuit.slimefun4.core.categories.SeasonalCategory;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
@ -28,7 +29,7 @@ import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class TestCategories {
class TestCategories {
private static ServerMock server;
private static SlimefunPlugin plugin;
@ -45,17 +46,23 @@ public class TestCategories {
}
@Test
public void testCategoryGetters() {
@DisplayName("Test the Getters for Category")
void testCategoryGetters() {
Category category = new Category(new NamespacedKey(plugin, "getter_test"), new CustomItem(Material.DIAMOND_AXE, "&6Testing"));
Assertions.assertEquals(3, category.getTier());
Assertions.assertEquals(new NamespacedKey(SlimefunPlugin.instance(), "getter_test"), category.getKey());
Assertions.assertEquals("Testing", category.getUnlocalizedName());
Assertions.assertEquals(0, category.getItems().size());
Assertions.assertNull(category.getAddon());
category.register(plugin);
Assertions.assertEquals(plugin, category.getAddon());
}
@Test
public void testAddItem() {
@DisplayName("Test adding an item to a Category")
void testAddItem() {
Category category = new Category(new NamespacedKey(plugin, "items_test"), new CustomItem(Material.DIAMOND_AXE, "&6Testing"));
SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "CATEGORY_ITEMS_TEST_ITEM", new CustomItem(Material.BAMBOO, "&6Test Bamboo"));
item.setCategory(category);
@ -73,7 +80,8 @@ public class TestCategories {
}
@Test
public void testHidden() {
@DisplayName("Test hidden Categories")
void testHidden() {
Category category = new Category(new NamespacedKey(plugin, "hiddenCategory"), new ItemStack(Material.BEACON));
Player player = server.addPlayer();
@ -103,7 +111,8 @@ public class TestCategories {
}
@Test
public void testContains() {
@DisplayName("Test Category#contains")
void testContains() {
SlimefunItem item = TestUtilities.mockSlimefunItem(plugin, "CATEGORY_TEST_ITEM_2", new CustomItem(Material.BOW, "&6Test Bow"));
item.register(plugin);
item.load();
@ -118,16 +127,17 @@ public class TestCategories {
}
@Test
public void testLockedCategoriesParents() {
@DisplayName("Test LockedCategory parental locking")
void testLockedCategoriesParents() {
Assertions.assertThrows(IllegalArgumentException.class, () -> new LockedCategory(new NamespacedKey(plugin, "locked"), new CustomItem(Material.GOLD_NUGGET, "&6Locked Test"), (NamespacedKey) null));
Category category = new Category(new NamespacedKey(plugin, "unlocked"), new CustomItem(Material.EMERALD, "&5I am SHERlocked"));
category.register();
category.register(plugin);
Category unregistered = new Category(new NamespacedKey(plugin, "unregistered"), new CustomItem(Material.EMERALD, "&5I am unregistered"));
LockedCategory locked = new LockedCategory(new NamespacedKey(plugin, "locked"), new CustomItem(Material.GOLD_NUGGET, "&6Locked Test"), category.getKey(), unregistered.getKey());
locked.register();
locked.register(plugin);
Assertions.assertTrue(locked.getParents().contains(category));
Assertions.assertFalse(locked.getParents().contains(unregistered));
@ -143,17 +153,18 @@ public class TestCategories {
}
@Test
public void testLockedCategoriesUnlocking() throws InterruptedException {
@DisplayName("Test an unlocked LockedCategory")
void testLockedCategoriesUnlocking() throws InterruptedException {
Player player = server.addPlayer();
PlayerProfile profile = TestUtilities.awaitProfile(player);
Assertions.assertThrows(IllegalArgumentException.class, () -> new LockedCategory(new NamespacedKey(plugin, "locked"), new CustomItem(Material.GOLD_NUGGET, "&6Locked Test"), (NamespacedKey) null));
Category category = new Category(new NamespacedKey(plugin, "parent"), new CustomItem(Material.EMERALD, "&5I am SHERlocked"));
category.register();
category.register(plugin);
LockedCategory locked = new LockedCategory(new NamespacedKey(plugin, "locked"), new CustomItem(Material.GOLD_NUGGET, "&6Locked Test"), category.getKey());
locked.register();
locked.register(plugin);
// No Items, so it should be unlocked
Assertions.assertTrue(locked.hasUnlocked(player, profile));
@ -176,7 +187,8 @@ public class TestCategories {
}
@Test
public void testSeasonalCategories() {
@DisplayName("Test a seasonal Category")
void testSeasonalCategories() {
// Category with current Month
Month month = LocalDate.now().getMonth();
SeasonalCategory category = new SeasonalCategory(new NamespacedKey(plugin, "seasonal"), month, 1, new CustomItem(Material.NETHER_STAR, "&cSeasonal Test"));
@ -196,16 +208,17 @@ public class TestCategories {
}
@Test
public void testFlexCategory() {
@DisplayName("Test the FlexCategory")
void testFlexCategory() {
FlexCategory category = new FlexCategory(new NamespacedKey(plugin, "flex"), new CustomItem(Material.REDSTONE, "&4Weird flex but ok")) {
@Override
public void open(Player p, PlayerProfile profile, SlimefunGuideLayout layout) {
public void open(Player p, PlayerProfile profile, SlimefunGuideMode layout) {
// Nothing
}
@Override
public boolean isVisible(Player p, PlayerProfile profile, SlimefunGuideLayout layout) {
public boolean isVisible(Player p, PlayerProfile profile, SlimefunGuideMode layout) {
return true;
}
};