1
mirror of https://github.com/StarWishsama/Slimefun4.git synced 2024-09-20 11:45:51 +00:00

Merge branch 'master' into MoreTalismans

This commit is contained in:
Senne Van Rompaey 2020-10-12 00:57:11 +02:00 committed by GitHub
commit 4d474de290
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
162 changed files with 3827 additions and 1120 deletions

View File

@ -4,6 +4,7 @@ on:
push:
paths:
- 'src/**'
- '!src/main/resources/languages/**'
- 'pom.xml'
jobs:
@ -15,11 +16,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v1
- name: Set up JDK 1.8
uses: actions/setup-java@master
uses: actions/checkout@v2.3.3
- name: Set up Java JDK 11
uses: actions/setup-java@v1.4.3
with:
java-version: 1.8
java-version: '11'
java-package: jdk
architecture: x64
- name: Run Discord Webhook
uses: Slimefun/discord-webhook@master
with:

View File

@ -4,9 +4,6 @@ on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:

View File

@ -37,6 +37,8 @@
* Added Elytra Cap
* Added Planks to Sticks recipe to the Table Saw
* Added "slimefun.gps.bypass" permission to open GPS devices anywhere
* (API) Added custom tags for developers
* The range of the Seeker Pickaxe is now configurable
#### Changes
* Improved Auto-Updater (Multi-Threading and more)
@ -68,6 +70,12 @@
* Fixed #2391
* Fixed #2403
* Fixed #2405
* Fixed #2412
* Fixed #2238
* Fixed #2439
* Fixed #2420
* Fixed #2422
* Fixed #2433
## Release Candidate 16 (07 Sep 2020)
https://thebusybiscuit.github.io/builds/TheBusyBiscuit/Slimefun4/stable/#16

View File

@ -262,6 +262,7 @@
<includes>
<include>*</include>
<include>tags/*</include>
<include>languages/*</include>
</includes>
</resource>
@ -344,7 +345,7 @@
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-java</artifactId>
<version>3.11.00</version>
<version>3.11.01</version>
<scope>compile</scope>
<exclusions>
<exclusion>

View File

@ -50,7 +50,7 @@ public enum MinecraftVersion {
*/
UNIT_TEST("Unit Test Environment");
public static final MinecraftVersion[] values = values();
public static final MinecraftVersion[] valuesCache = values();
private final String name;
private final String prefix;

View File

@ -0,0 +1,48 @@
package io.github.thebusybiscuit.slimefun4.api.exceptions;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.NamespacedKey;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
/**
* An {@link TagMisconfigurationException} is thrown whenever a {@link SlimefunTag}
* contains illegal, invalid or unknown values.
*
* @author TheBusyBiscuit
*
*/
public class TagMisconfigurationException extends Exception {
private static final long serialVersionUID = 5412127960821774280L;
/**
* This constructs a new {@link TagMisconfigurationException} for the given
* {@link SlimefunTag}'s {@link NamespacedKey} with the provided context.
*
* @param key
* The {@link NamespacedKey} of our {@link SlimefunTag}
* @param message
* The message to display
*/
@ParametersAreNonnullByDefault
public TagMisconfigurationException(NamespacedKey key, String message) {
super("Tag '" + key + "' has been misconfigured: " + message);
}
/**
* This constructs a new {@link TagMisconfigurationException} for the given
* {@link SlimefunTag}'s {@link NamespacedKey} with the provided context.
*
* @param key
* The {@link NamespacedKey} of our {@link SlimefunTag}
* @param cause
* The {@link Throwable} which has caused this to happen
*/
@ParametersAreNonnullByDefault
public TagMisconfigurationException(NamespacedKey key, Throwable cause) {
super("Tag '" + key + "' has been misconfigured (" + cause.getMessage() + ')', cause);
}
}

View File

@ -201,15 +201,19 @@ public class ResourceManager {
menu.addItem(47, ChestMenuUtils.getPreviousButton(p, page + 1, pages));
menu.addMenuClickHandler(47, (pl, slot, item, action) -> {
if (page > 0)
if (page > 0) {
scan(pl, block, page - 1);
}
return false;
});
menu.addItem(51, ChestMenuUtils.getNextButton(p, page + 1, pages));
menu.addMenuClickHandler(51, (pl, slot, item, action) -> {
if (page + 1 < pages)
if (page + 1 < pages) {
scan(pl, block, page + 1);
}
return false;
});

View File

@ -148,10 +148,12 @@ public class GPSNetwork {
int index = 0;
for (Location l : getTransmitters(p.getUniqueId())) {
if (index >= inventory.length)
if (index >= inventory.length) {
break;
}
SlimefunItem sfi = BlockStorage.check(l);
if (sfi instanceof GPSTransmitter) {
int slot = inventory[index];
@ -216,8 +218,10 @@ public class GPSNetwork {
int index = 0;
for (Waypoint waypoint : profile.getWaypoints()) {
if (index >= inventory.length)
if (index >= inventory.length) {
break;
}
int slot = inventory[index];
Location l = waypoint.getLocation();

View File

@ -92,8 +92,9 @@ public final class TeleportationManager {
@ParametersAreNonnullByDefault
public int getTeleportationTime(int complexity, Location source, Location destination) {
if (complexity < 100)
if (complexity < 100) {
return 100;
}
int speed = 50_000 + complexity * complexity;
return 1 + Math.min(4 * distanceSquared(source, destination) / speed, 40);

View File

@ -119,6 +119,17 @@ public class ItemSetting<T> {
return c.isInstance(defaultValue);
}
/**
* This is an error message which should provide further context on what values
* are allowed.
*
* @return An error message which is displayed when this {@link ItemSetting} is misconfigured.
*/
@Nonnull
protected String getErrorMessage() {
return "Only '" + defaultValue.getClass().getSimpleName() + "' values are allowed!";
}
/**
* This method is called by a {@link SlimefunItem} which wants to load its {@link ItemSetting}
* from the {@link Config} file.
@ -132,7 +143,14 @@ public class ItemSetting<T> {
Object configuredValue = SlimefunPlugin.getItemCfg().getValue(item.getID() + '.' + getKey());
if (defaultValue.getClass().isInstance(configuredValue)) {
this.value = (T) configuredValue;
if (validateInput((T) configuredValue)) {
this.value = (T) configuredValue;
} 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());
}
} else {
this.value = defaultValue;
String found = configuredValue == null ? "null" : configuredValue.getClass().getSimpleName();
@ -144,4 +162,10 @@ public class ItemSetting<T> {
}
}
@Override
public String toString() {
T currentValue = this.value != null ? this.value : defaultValue;
return getClass().getSimpleName() + " {" + getKey() + " = " + currentValue + " (default: " + getDefaultValue() + ")";
}
}

View File

@ -0,0 +1,63 @@
package io.github.thebusybiscuit.slimefun4.api.items.settings;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
/**
* This variation of {@link ItemSetting} allows you to define an {@link Double} range
* and enforces this range using the {@link #validateInput(Double)} method.
*
* @author TheBusyBiscuit
*
* @see ItemSetting
* @see IntRangeSetting
*
*/
public class DoubleRangeSetting extends ItemSetting<Double> {
private final double min;
private final double max;
@ParametersAreNonnullByDefault
public DoubleRangeSetting(String key, double min, double defaultValue, double max) {
super(key, defaultValue);
Validate.isTrue(defaultValue >= min && defaultValue <= max, "The default value is not in range.");
this.min = min;
this.max = max;
}
@Nonnull
@Override
protected String getErrorMessage() {
return "Only decimal numbers from " + min + '-' + max + "(inclusive) are allowed!";
}
@Override
public boolean validateInput(Double input) {
return super.validateInput(input) && input >= min && input <= max;
}
/**
* This returns the minimum value of this {@link DoubleRangeSetting}.
*
* @return The minimum value
*/
public final double getMinimum() {
return min;
}
/**
* This returns the maximum value of this {@link DoubleRangeSetting}.
*
* @return The maximum value
*/
public final double getMaximum() {
return max;
}
}

View File

@ -0,0 +1,72 @@
package io.github.thebusybiscuit.slimefun4.api.items.settings;
import java.util.Arrays;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
/**
* This variation of {@link ItemSetting} allows you to allow {@link Enum} constants to be
* used for {@link ItemSetting} validation.
*
* @author TheBusyBiscuit
*
* @see ItemSetting
*
*/
public class EnumSetting<T extends Enum<T>> extends ItemSetting<String> {
private final Class<T> enumClass;
@ParametersAreNonnullByDefault
public EnumSetting(String key, Class<T> enumClass, T defaultValue) {
super(key, defaultValue.name());
this.enumClass = enumClass;
}
@Nonnull
@Override
protected String getErrorMessage() {
String values = Arrays.stream(getAllowedValues()).map(Enum::name).collect(Collectors.joining(", "));
return "The following values are valid: " + values;
}
/**
* This returns an array of valid {@link Enum} values.
* This method may be overridden to further limit the allowed values.
*
* @return An array of allowed {@link Enum} constants
*/
public T[] getAllowedValues() {
return enumClass.getEnumConstants();
}
/**
* This will attempt to get the configured value as a constant of the desired {@link Enum}.
*
* @return The value as an {@link Enum} constant
*/
public T getAsEnumConstant() {
return Enum.valueOf(enumClass, getValue());
}
@Override
public boolean validateInput(String input) {
if (!super.validateInput(input)) {
return false;
} else {
for (Enum<T> value : getAllowedValues()) {
if (value.name().equals(input)) {
return true;
}
}
return false;
}
}
}

View File

@ -0,0 +1,63 @@
package io.github.thebusybiscuit.slimefun4.api.items.settings;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
/**
* This variation of {@link ItemSetting} allows you to define an {@link Integer} range
* and enforces this range using the {@link #validateInput(Integer)} method.
*
* @author TheBusyBiscuit
*
* @see ItemSetting
* @see DoubleRangeSetting
*
*/
public class IntRangeSetting extends ItemSetting<Integer> {
private final int min;
private final int max;
@ParametersAreNonnullByDefault
public IntRangeSetting(String key, int min, int defaultValue, int max) {
super(key, defaultValue);
Validate.isTrue(defaultValue >= min && defaultValue <= max, "The default value is not in range.");
this.min = min;
this.max = max;
}
@Nonnull
@Override
protected String getErrorMessage() {
return "Only whole numbers from " + min + '-' + max + "(inclusive) are allowed!";
}
@Override
public boolean validateInput(Integer input) {
return super.validateInput(input) && input >= min && input <= max;
}
/**
* This returns the minimum value of this {@link IntRangeSetting}.
*
* @return The minimum value
*/
public final int getMinimum() {
return min;
}
/**
* This returns the maximum value of this {@link IntRangeSetting}.
*
* @return The maximum value
*/
public final int getMaximum() {
return max;
}
}

View File

@ -0,0 +1,83 @@
package io.github.thebusybiscuit.slimefun4.api.items.settings;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Material;
import org.bukkit.Tag;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
/**
* This variation of {@link ItemSetting} allows you to define a default {@link Tag}.
* The {@link Tag} will be translated into a {@link String} {@link List} which the user
* can then configure as they wish.
*
* It also validates all inputs to be a valid {@link Material}.
*
* @author TheBusyBiscuit
*
* @see ItemSetting
*
*/
public class MaterialTagSetting extends ItemSetting<List<String>> {
private final Tag<Material> defaultTag;
@ParametersAreNonnullByDefault
public MaterialTagSetting(String key, Tag<Material> defaultTag) {
super(key, getAsStringList(defaultTag));
this.defaultTag = defaultTag;
}
/**
* This {@link Tag} holds the default values for this {@link MaterialTagSetting}.
*
* @return The default {@link Tag}
*/
@Nonnull
public Tag<Material> getDefaultTag() {
return defaultTag;
}
@Nonnull
@Override
protected String getErrorMessage() {
return "This List can only contain Materials in the format of e.g. REDSTONE_BLOCK";
}
@Override
public boolean validateInput(List<String> input) {
if (super.validateInput(input)) {
for (String value : input) {
Material material = Material.matchMaterial(value);
// This value is not a valid material, the setting is not valid.
if (material == null) {
return false;
}
}
return true;
} else {
return false;
}
}
/**
* Internal method to turn a {@link Tag} into a {@link List} of {@link String Strings}.
*
* @param tag
* Our {@link Tag}
* @return The {@link String} {@link List}
*/
@Nonnull
private static List<String> getAsStringList(@Nonnull Tag<Material> tag) {
return tag.getValues().stream().map(Material::name).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,4 @@
/**
* This package contains various sub classes of {@link io.github.thebusybiscuit.slimefun4.api.items.ItemSetting}.
*/
package io.github.thebusybiscuit.slimefun4.api.items.settings;

View File

@ -28,13 +28,14 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.BackpackListe
*/
public class PlayerBackpack {
private static final String CONFIG_PREFIX = "backpacks.";
private final PlayerProfile profile;
private final int id;
private final Config cfg;
private Inventory inventory;
private int size;
private static final String CONFIG_PREFIX = "backpacks.";
/**
* This constructor loads an existing Backpack

View File

@ -4,6 +4,8 @@ import java.util.Optional;
import java.util.OptionalInt;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
import org.bukkit.Keyed;
import org.bukkit.NamespacedKey;
@ -27,10 +29,11 @@ public class StatusEffect implements Keyed {
private final NamespacedKey key;
public StatusEffect(NamespacedKey key) {
public StatusEffect(@Nonnull NamespacedKey key) {
this.key = key;
}
@Nonnull
@Override
public NamespacedKey getKey() {
return key;
@ -48,7 +51,7 @@ public class StatusEffect implements Keyed {
* @param unit
* The {@link TimeUnit} for the given duration
*/
public void add(Player p, int duration, TimeUnit unit) {
public void add(@Nonnull Player p, int duration, @Nonnull TimeUnit unit) {
add(p, 1, duration, unit);
}
@ -64,7 +67,7 @@ public class StatusEffect implements Keyed {
* @param unit
* The {@link TimeUnit} for the given duration
*/
public void add(Player p, int level, int duration, TimeUnit unit) {
public void add(@Nonnull Player p, int level, int duration, @Nonnull TimeUnit unit) {
PersistentDataAPI.setString(p, getKey(), level + ";" + System.currentTimeMillis() + unit.toMillis(duration));
}
@ -77,7 +80,7 @@ public class StatusEffect implements Keyed {
* @param level
* The level of this effect
*/
public void addPermanent(Player p, int level) {
public void addPermanent(@Nonnull Player p, int level) {
PersistentDataAPI.setString(p, getKey(), level + ";0");
}
@ -91,7 +94,7 @@ public class StatusEffect implements Keyed {
* The {@link Player} to check for
* @return Whether this {@link StatusEffect} is currently applied
*/
public boolean isPresent(Player p) {
public boolean isPresent(@Nonnull Player p) {
Optional<String> optional = PersistentDataAPI.getOptionalString(p, getKey());
if (optional.isPresent()) {
@ -104,8 +107,9 @@ public class StatusEffect implements Keyed {
clear(p);
return false;
}
} else
} else {
return false;
}
}
/**
@ -116,15 +120,16 @@ public class StatusEffect implements Keyed {
* The {@link Player} to check for
* @return An {@link OptionalInt} that describes the result
*/
public OptionalInt getLevel(Player p) {
@Nonnull
public OptionalInt getLevel(@Nonnull Player p) {
Optional<String> optional = PersistentDataAPI.getOptionalString(p, getKey());
if (optional.isPresent()) {
String[] data = PatternUtils.SEMICOLON.split(optional.get());
return OptionalInt.of(Integer.parseInt(data[0]));
} else
} else {
return OptionalInt.empty();
}
}
/**
@ -133,7 +138,7 @@ public class StatusEffect implements Keyed {
* @param p
* The {@link Player} to clear it from
*/
public void clear(Player p) {
public void clear(@Nonnull Player p) {
PersistentDataAPI.remove(p, getKey());
}

View File

@ -11,6 +11,9 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nonnull;
import org.apache.commons.lang.Validate;
import org.bukkit.Server;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@ -47,7 +50,7 @@ import me.mrCookieSlime.Slimefun.api.inventory.UniversalBlockMenu;
* @author TheBusyBiscuit
*
*/
public class SlimefunRegistry {
public final class SlimefunRegistry {
private final Map<String, SlimefunItem> slimefunIds = new HashMap<>();
private final List<SlimefunItem> slimefunItems = new ArrayList<>();
@ -86,7 +89,9 @@ public class SlimefunRegistry {
private final Map<String, ItemStack> automatedCraftingChamberRecipes = new HashMap<>();
public void load(Config cfg) {
public void load(@Nonnull Config cfg) {
Validate.notNull(cfg, "The Config cannot be null!");
boolean showVanillaRecipes = cfg.getBoolean("guide.show-vanilla-recipes");
layouts.put(SlimefunGuideLayout.CHEST, new ChestSlimefunGuide(showVanillaRecipes));

View File

@ -49,8 +49,9 @@ class ResearchCommand extends SubCommand {
} else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.not-online", true, msg -> msg.replace(PLACEHOLDER_PLAYER, args[1]));
}
} else
} else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true);
}
} else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.usage", true, msg -> msg.replace("%usage%", "/sf research <Player> <all/reset/Research>"));
}

View File

@ -29,8 +29,9 @@ class StatsCommand extends SubCommand {
} else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.not-online", true, msg -> msg.replace("%player%", args[1]));
}
} else
} else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true);
}
} else if (sender instanceof Player) {
PlayerProfile.get((Player) sender, profile -> profile.sendStats(sender));
} else {

View File

@ -78,15 +78,20 @@ public final class SlimefunGuide {
}
public static void openCategory(PlayerProfile profile, Category category, SlimefunGuideLayout layout, int selectedPage) {
if (category == null)
if (category == null) {
return;
}
SlimefunPlugin.getRegistry().getGuideLayout(layout).openCategory(profile, category, selectedPage);
}
public static void openSearch(PlayerProfile profile, String input, boolean survival, boolean addToHistory) {
SlimefunGuideImplementation layout = SlimefunPlugin.getRegistry().getGuideLayout(SlimefunGuideLayout.CHEST);
if (!survival)
if (!survival) {
layout = SlimefunPlugin.getRegistry().getGuideLayout(SlimefunGuideLayout.CHEAT_SHEET);
}
layout.openSearch(profile, input, addToHistory);
}

View File

@ -31,6 +31,6 @@ public enum SlimefunGuideLayout {
*/
CHEAT_SHEET;
public static final SlimefunGuideLayout[] values = values();
public static final SlimefunGuideLayout[] valuesCache = values();
}

View File

@ -98,7 +98,7 @@ class GuideLayoutOption implements SlimefunGuideOption<SlimefunGuideLayout> {
@Override
public Optional<SlimefunGuideLayout> getSelectedOption(Player p, ItemStack guide) {
for (SlimefunGuideLayout layout : SlimefunGuideLayout.values) {
for (SlimefunGuideLayout layout : SlimefunGuideLayout.valuesCache) {
if (SlimefunUtils.isItemSimilar(guide, SlimefunGuide.getItem(layout), true, false)) {
return Optional.of(layout);
}

View File

@ -1,6 +1,9 @@
package io.github.thebusybiscuit.slimefun4.core.handlers;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nonnull;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
@ -10,7 +13,6 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.GlassPane;
import io.github.thebusybiscuit.cscorelib2.collections.LoopIterator;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollection;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.RainbowBlock;
@ -34,18 +36,22 @@ public class RainbowTickHandler extends BlockTicker {
private final boolean glassPanes;
private Material material;
public RainbowTickHandler(Material... materials) {
public RainbowTickHandler(@Nonnull List<Material> materials) {
Validate.noNullElements(materials, "A RainbowTicker cannot have a Material that is null!");
if (materials.length == 0) {
if (materials.isEmpty()) {
throw new IllegalArgumentException("A RainbowTicker must have at least one Material associated with it!");
}
glassPanes = containsGlassPanes(materials);
iterator = new LoopIterator<>(Arrays.asList(materials));
iterator = new LoopIterator<>(materials);
material = iterator.next();
}
public RainbowTickHandler(Material... materials) {
this(Arrays.asList(materials));
}
/**
* This method checks whether a given {@link Material} array contains any {@link Material}
* that would result in a {@link GlassPane} {@link BlockData}.
@ -57,7 +63,7 @@ public class RainbowTickHandler extends BlockTicker {
*
* @return Whether the array contained any {@link GlassPane} materials
*/
private boolean containsGlassPanes(Material[] materials) {
private boolean containsGlassPanes(@Nonnull List<Material> materials) {
if (SlimefunPlugin.getMinecraftVersion() == MinecraftVersion.UNIT_TEST) {
// BlockData is not available to us during Unit Tests :/
return false;
@ -75,10 +81,6 @@ public class RainbowTickHandler extends BlockTicker {
return false;
}
public RainbowTickHandler(MaterialCollection collection) {
this(collection.getAsArray());
}
@Override
public void tick(Block b, SlimefunItem item, Config data) {
if (b.getType() == Material.AIR) {

View File

@ -48,12 +48,7 @@ public class MetricsService {
private boolean hasDownloadedUpdate = false;
static {
Unirest.config()
.concurrency(2, 1)
.setDefaultHeader("User-Agent", "MetricsModule Auto-Updater")
.setDefaultHeader("Accept", "application/vnd.github.v3+json")
.enableCookieManagement(false)
.cookieSpec("ignoreCookies");
Unirest.config().concurrency(2, 1).setDefaultHeader("User-Agent", "MetricsModule Auto-Updater").setDefaultHeader("Accept", "application/vnd.github.v3+json").enableCookieManagement(false).cookieSpec("ignoreCookies");
}
public MetricsService(@Nonnull SlimefunPlugin plugin) {
@ -221,7 +216,7 @@ public class MetricsService {
return true;
}
} catch (UnirestException e) {
plugin.getLogger().log(Level.WARNING, "Failed to fetch the latest jar file from the builds page. Perhaps GitHub is down?");
plugin.getLogger().log(Level.WARNING, "Failed to fetch the latest jar file from the builds page. Perhaps GitHub is down? Response: {0}", e.getMessage());
} catch (IOException e) {
plugin.getLogger().log(Level.WARNING, "Failed to replace the old metric file with the new one. Please do this manually! Error: {0}", e.getMessage());
}

View File

@ -85,7 +85,7 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
protected abstract void addLanguage(@Nonnull String id, @Nonnull String texture);
protected void loadEmbeddedLanguages() {
for (SupportedLanguage lang : SupportedLanguage.values) {
for (SupportedLanguage lang : SupportedLanguage.valuesCache) {
if (lang.isReadyForRelease() || SlimefunPlugin.getUpdater().getBranch() != SlimefunBranch.STABLE) {
addLanguage(lang.getLanguageId(), lang.getTexture());
}

View File

@ -58,7 +58,7 @@ enum SupportedLanguage {
MACEDONIAN("mk", false, "a0e0b0b5d87a855466980a101a757bcdb5f77d9f7287889f3efa998ee0472fc0"),
TAGALOG("tl", true, "9306c0c1ce6a9c61bb42a572c49e6d0ed20e0e6b3d122cc64c339cbf78e9e937");
public static final SupportedLanguage[] values = values();
public static final SupportedLanguage[] valuesCache = values();
private final String id;
private final boolean releaseReady;

View File

@ -99,6 +99,9 @@ public class Translators {
addTranslator("Dr4gonD", "DragonD", SupportedLanguage.DUTCH, true);
addTranslator("svr333", SupportedLanguage.DUTCH, false);
addTranslator("PabloMarcendo", SupportedLanguage.DUTCH, true);
addTranslator("milvantiou", SupportedLanguage.DUTCH, true);
addTranslator("Sven313D", SupportedLanguage.DUTCH, true);
addTranslator("TypischTeun", SupportedLanguage.DUTCH, true);
// Translators - Danish
addTranslator("Mini-kun", SupportedLanguage.DANISH, true);

View File

@ -31,7 +31,7 @@ public enum PerformanceRating implements Predicate<Float> {
HURTFUL(ChatColor.DARK_RED, 500),
BAD(ChatColor.DARK_RED, Float.MAX_VALUE);
public static final PerformanceRating[] values = values();
public static final PerformanceRating[] valuesCache = values();
private final ChatColor color;
private final float threshold;

View File

@ -296,7 +296,7 @@ public class SlimefunProfiler {
public PerformanceRating getPerformance() {
float percentage = getPercentageOfTick();
for (PerformanceRating rating : PerformanceRating.values) {
for (PerformanceRating rating : PerformanceRating.valuesCache) {
if (rating.test(percentage)) {
return rating;
}

View File

@ -30,6 +30,7 @@ import io.github.thebusybiscuit.cscorelib2.protection.ProtectionManager;
import io.github.thebusybiscuit.cscorelib2.reflection.ReflectionUtils;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.api.exceptions.TagMisconfigurationException;
import io.github.thebusybiscuit.slimefun4.api.gps.GPSNetwork;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.SlimefunRegistry;
@ -99,6 +100,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.setup.SlimefunItemSetup
import io.github.thebusybiscuit.slimefun4.implementation.tasks.ArmorTask;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.SlimefunStartupTask;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.TickerTask;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.CSCoreLibPlugin.CSCoreLib;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
@ -175,7 +177,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
registry.load(config);
} else if (getServer().getPluginManager().isPluginEnabled("CS-CoreLib")) {
long timestamp = System.nanoTime();
PaperLib.suggestPaper(this);
// We wanna ensure that the Server uses a compatible version of Minecraft
@ -228,6 +229,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
getLogger().log(Level.INFO, "Loading GEO-Resources...");
GEOResourcesSetup.setup();
getLogger().log(Level.INFO, "Loading Tags...");
loadTags();
getLogger().log(Level.INFO, "Loading items...");
loadItems();
@ -310,7 +314,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
String currentVersion = ReflectionUtils.getVersion();
if (currentVersion.startsWith("v")) {
for (MinecraftVersion version : MinecraftVersion.values) {
for (MinecraftVersion version : MinecraftVersion.valuesCache) {
if (version.matches(currentVersion)) {
minecraftVersion = version;
return false;
@ -337,7 +341,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
private Collection<String> getSupportedVersions() {
List<String> list = new ArrayList<>();
for (MinecraftVersion version : MinecraftVersion.values) {
for (MinecraftVersion version : MinecraftVersion.valuesCache) {
if (version != MinecraftVersion.UNKNOWN) {
list.add(version.getName());
}
@ -489,6 +493,16 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
new PlayerProfileListener(this);
}
private void loadTags() {
for (SlimefunTag tag : SlimefunTag.valuesCache) {
try {
tag.reload();
} catch (TagMisconfigurationException e) {
getLogger().log(Level.SEVERE, e, () -> "Failed to load Tag: " + tag.name());
}
}
}
private void loadItems() {
try {
SlimefunItemSetup.setup(this);

View File

@ -233,16 +233,22 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
menu.addItem(46, ChestMenuUtils.getPreviousButton(p, page, pages));
menu.addMenuClickHandler(46, (pl, slot, item, action) -> {
int next = page - 1;
if (next != page && next > 0)
if (next != page && next > 0) {
openCategory(profile, category, next);
}
return false;
});
menu.addItem(52, ChestMenuUtils.getNextButton(p, page, pages));
menu.addMenuClickHandler(52, (pl, slot, item, action) -> {
int next = page + 1;
if (next != page && next <= pages)
if (next != page && next <= pages) {
openCategory(profile, category, next);
}
return false;
});

View File

@ -4,12 +4,12 @@ import java.util.concurrent.ThreadLocalRandom;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.Tag;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.collections.RandomizedSet;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -25,7 +25,7 @@ public class FisherAndroid extends ProgrammableAndroid {
super(category, tier, item, recipeType, recipe);
// Fish
for (Material fish : MaterialCollections.getAllFishItems()) {
for (Material fish : Tag.ITEMS_FISHES.getValues()) {
fishingLoot.add(new ItemStack(fish), 25);
}

View File

@ -146,18 +146,18 @@ enum Instruction {
});
private static final Map<String, Instruction> nameLookup = new HashMap<>();
public static final Instruction[] values = values();
public static final Instruction[] valuesCache = values();
static {
for (Instruction instruction : valuesCache) {
nameLookup.put(instruction.name(), instruction);
}
}
private final ItemStack item;
private final AndroidType type;
private final AndroidAction method;
static {
for (Instruction instruction : values) {
nameLookup.put(instruction.name(), instruction);
}
}
@ParametersAreNonnullByDefault
Instruction(AndroidType type, HeadTexture head, @Nullable AndroidAction method) {
this.type = type;
@ -198,7 +198,7 @@ enum Instruction {
* @return The {@link Instruction} or null if it does not exist.
*/
@Nullable
public static Instruction getFromCache(@Nonnull String value) {
public static Instruction getInstruction(@Nonnull String value) {
Validate.notNull(value, "An Instruction cannot be null!");
return nameLookup.get(value);
}

View File

@ -11,10 +11,10 @@ import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.events.AndroidMineEvent;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -40,7 +40,7 @@ public class MinerAndroid extends ProgrammableAndroid {
protected void dig(Block b, BlockMenu menu, Block block) {
Collection<ItemStack> drops = block.getDrops(effectivePickaxe);
if (!MaterialCollections.getAllUnbreakableBlocks().contains(block.getType()) && !drops.isEmpty()) {
if (!SlimefunTag.UNBREAKABLE_MATERIALS.isTagged(block.getType()) && !drops.isEmpty()) {
OfflinePlayer owner = Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner")));
if (SlimefunPlugin.getProtectionManager().hasPermission(owner, block.getLocation(), ProtectableAction.BREAK_BLOCK)) {
@ -71,7 +71,7 @@ public class MinerAndroid extends ProgrammableAndroid {
protected void moveAndDig(Block b, BlockMenu menu, BlockFace face, Block block) {
Collection<ItemStack> drops = block.getDrops(effectivePickaxe);
if (!MaterialCollections.getAllUnbreakableBlocks().contains(block.getType()) && !drops.isEmpty()) {
if (!SlimefunTag.UNBREAKABLE_MATERIALS.isTagged(block.getType()) && !drops.isEmpty()) {
OfflinePlayer owner = Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner")));
if (SlimefunPlugin.getProtectionManager().hasPermission(owner, block.getLocation(), ProtectableAction.BREAK_BLOCK)) {

View File

@ -257,7 +257,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
return false;
});
} else {
Instruction instruction = Instruction.getFromCache(script[i]);
Instruction instruction = Instruction.getInstruction(script[i]);
if (instruction == null) {
SlimefunPlugin.instance().getLogger().log(Level.WARNING, "Failed to parse Android instruction: {0}, maybe your server is out of date?", script[i]);
@ -493,7 +493,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
protected List<Instruction> getValidScriptInstructions() {
List<Instruction> list = new ArrayList<>();
for (Instruction part : Instruction.values) {
for (Instruction part : Instruction.valuesCache) {
if (part == Instruction.START || part == Instruction.REPEAT) {
continue;
}
@ -646,7 +646,7 @@ public class ProgrammableAndroid extends SlimefunItem implements InventoryBlock,
}
BlockStorage.addBlockInfo(b, "fuel", String.valueOf(fuel - 1));
Instruction instruction = Instruction.getFromCache(script[index]);
Instruction instruction = Instruction.getInstruction(script[index]);
if (instruction == null) {
SlimefunPlugin.instance().getLogger().log(Level.WARNING, "Failed to parse Android instruction: {0}, maybe your server is out of date?", script[index]);

View File

@ -9,6 +9,9 @@ import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
@ -22,6 +25,12 @@ 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}.
*
* @author TheBusyBiscuit
*
*/
public final class Script {
private final Config config;
@ -29,7 +38,13 @@ public final class Script {
private final String author;
private final String code;
private Script(Config config) {
/**
* This constructs a new {@link Script} from the given {@link Config}.
*
* @param config
* The {@link Config}
*/
private Script(@Nonnull Config config) {
Validate.notNull(config);
this.config = config;
@ -52,6 +67,7 @@ public final class Script {
*
* @return The name
*/
@Nonnull
public String getName() {
return name;
}
@ -62,6 +78,7 @@ public final class Script {
*
* @return The author of this {@link Script}
*/
@Nonnull
public String getAuthor() {
return author;
}
@ -73,6 +90,7 @@ public final class Script {
*
* @return The code for this {@link Script}
*/
@Nonnull
public String getSourceCode() {
return code;
}
@ -86,7 +104,7 @@ public final class Script {
*
* @return Whether the given {@link OfflinePlayer} is the author of this {@link Script}.
*/
public boolean isAuthor(OfflinePlayer p) {
public boolean isAuthor(@Nonnull OfflinePlayer p) {
return p.getUniqueId().equals(config.getUUID("author"));
}
@ -99,7 +117,7 @@ public final class Script {
*
* @return Whether the given {@link Player} is able to rate this {@link Script}
*/
public boolean canRate(Player p) {
public boolean canRate(@Nonnull Player p) {
if (isAuthor(p)) {
return false;
}
@ -109,7 +127,8 @@ public final class Script {
return !upvoters.contains(p.getUniqueId().toString()) && !downvoters.contains(p.getUniqueId().toString());
}
ItemStack getAsItemStack(ProgrammableAndroid android, Player p) {
@Nonnull
ItemStack getAsItemStack(@Nonnull ProgrammableAndroid android, @Nonnull Player p) {
List<String> lore = new LinkedList<>();
lore.add("&7by &r" + getAuthor());
lore.add("");
@ -128,6 +147,7 @@ public final class Script {
return new CustomItem(android.getItem(), "&b" + getName(), lore.toArray(new String[0]));
}
@Nonnull
private String getScriptRatingPercentage() {
float percentage = getRating();
return NumberUtils.getColorFromPercentage(percentage) + String.valueOf(percentage) + ChatColor.RESET + "% ";
@ -181,7 +201,7 @@ public final class Script {
config.save();
}
public void rate(Player p, boolean positive) {
public void rate(@Nonnull Player p, boolean positive) {
config.reload();
String path = "rating." + (positive ? "positive" : "negative");
@ -192,7 +212,8 @@ public final class Script {
config.save();
}
public static List<Script> getUploadedScripts(AndroidType androidType) {
@Nonnull
public static List<Script> getUploadedScripts(@Nonnull AndroidType androidType) {
List<Script> scripts = new LinkedList<>();
loadScripts(scripts, androidType);
@ -205,7 +226,7 @@ public final class Script {
return scripts;
}
private static void loadScripts(List<Script> scripts, AndroidType type) {
private static void loadScripts(@Nonnull List<Script> scripts, @Nonnull AndroidType type) {
File directory = new File("plugins/Slimefun/scripts/" + type.name());
if (!directory.exists()) {
directory.mkdirs();
@ -228,6 +249,7 @@ public final class Script {
}
}
@ParametersAreNonnullByDefault
public static void upload(Player p, AndroidType androidType, int id, String name, String code) {
Config config = new Config("plugins/Slimefun/scripts/" + androidType.name() + '/' + p.getName() + ' ' + id + ".sfs");

View File

@ -1,6 +1,9 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.backpacks;
import org.bukkit.Material;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
@ -9,6 +12,7 @@ import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.BackpackListener;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -28,6 +32,7 @@ public class SlimefunBackpack extends SimpleSlimefunItem<ItemUseHandler> {
private final int size;
@ParametersAreNonnullByDefault
public SlimefunBackpack(int size, Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
@ -55,9 +60,9 @@ public class SlimefunBackpack extends SimpleSlimefunItem<ItemUseHandler> {
*
* @return Whether the given {@link ItemStack} is allowed to be put into this {@link SlimefunBackpack}
*/
public boolean isItemAllowed(ItemStack item, SlimefunItem itemAsSlimefunItem) {
public boolean isItemAllowed(@Nonnull ItemStack item, @Nullable SlimefunItem itemAsSlimefunItem) {
// Shulker Boxes are not allowed!
if (item.getType() == Material.SHULKER_BOX || item.getType().toString().endsWith("_SHULKER_BOX")) {
if (SlimefunTag.SHULKER_BOXES.isTagged(item.getType())) {
return false;
}

View File

@ -2,7 +2,6 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.blocks;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
@ -18,14 +17,15 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.events.BlockPlacerPlaceEvent;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.MaterialTagSetting;
import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockDispenseHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import io.papermc.lib.PaperLib;
import io.papermc.lib.features.blockstatesnapshot.BlockStateSnapshotResult;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -47,7 +47,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
*/
public class BlockPlacer extends SlimefunItem {
private final ItemSetting<List<String>> blacklist = new ItemSetting<>("unplaceable-blocks", MaterialCollections.getAllUnbreakableBlocks().stream().map(Material::name).collect(Collectors.toList()));
private final ItemSetting<List<String>> blacklist = new MaterialTagSetting("unplaceable-blocks", SlimefunTag.UNBREAKABLE_MATERIALS);
public BlockPlacer(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
@ -72,10 +72,13 @@ public class BlockPlacer extends SlimefunItem {
private BlockDispenseHandler onBlockDispense() {
return (e, dispenser, facedBlock, machine) -> {
if (!hasPermission(dispenser, facedBlock)) {
e.setCancelled(true);
return;
}
if (isShulkerBox(e.getItem().getType())) {
Material material = e.getItem().getType();
if (SlimefunTag.SHULKER_BOXES.isTagged(material)) {
// Since vanilla Dispensers can already place Shulker boxes, we
// simply fallback to the vanilla behaviour.
return;
@ -83,7 +86,14 @@ public class BlockPlacer extends SlimefunItem {
e.setCancelled(true);
if (facedBlock.isEmpty() && e.getItem().getType().isBlock() && !isBlacklisted(e.getItem().getType())) {
if (!material.isBlock() || SlimefunTag.BLOCK_PLACER_IGNORED_MATERIALS.isTagged(material)) {
// Some materials cannot be reliably placed, like beds, it would look
// kinda wonky, so we just ignore these altogether.
// The event has already been cancelled too, so they won't drop.
return;
}
if (facedBlock.isEmpty() && !isBlacklisted(material)) {
SlimefunItem item = SlimefunItem.getByItem(e.getItem());
if (item != null) {
@ -123,10 +133,6 @@ public class BlockPlacer extends SlimefunItem {
return SlimefunPlugin.getProtectionManager().hasPermission(player, target, ProtectableAction.PLACE_BLOCK);
}
private boolean isShulkerBox(Material type) {
return type == Material.SHULKER_BOX || type.name().endsWith("_SHULKER_BOX");
}
private boolean isBlacklisted(Material type) {
for (String blockType : blacklist.getValue()) {
if (type.toString().equals(blockType)) {

View File

@ -17,13 +17,13 @@ import org.bukkit.block.data.Waterlogged;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
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.SlimefunUtils;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
@ -67,7 +67,7 @@ public class Crucible extends SimpleSlimefunItem<BlockUseHandler> implements Rec
items.add(new ItemStack(Material.WATER_BUCKET));
}
for (Material sapling : MaterialCollections.getAllTerracottaColors()) {
for (Material sapling : SlimefunTag.TERRACOTTA.getValues()) {
items.add(new ItemStack(sapling, 12));
items.add(new ItemStack(Material.LAVA_BUCKET));
}

View File

@ -11,6 +11,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.DoubleRangeSetting;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
@ -24,7 +25,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class InfusedHopper extends SimpleSlimefunItem<BlockTicker> {
private final ItemSetting<Boolean> silent = new ItemSetting<>("silent", false);
private final ItemSetting<Double> radius = new ItemSetting<>("radius", 3.5);
private final ItemSetting<Double> radius = new DoubleRangeSetting("radius", 0.1, 3.5, Double.MAX_VALUE);
public InfusedHopper(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);

View File

@ -6,12 +6,12 @@ import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
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.ColoredMaterials;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -100,7 +100,7 @@ abstract class AbstractCargoNode extends SlimefunItem {
menu.replaceExistingItem(slotCurrent, new CustomItem(HeadTexture.CHEST_TERMINAL.getAsItemStack(), "&bChannel ID: &3" + (channel + 1)));
menu.addMenuClickHandler(slotCurrent, ChestMenuUtils.getEmptyClickHandler());
} else {
menu.replaceExistingItem(slotCurrent, new CustomItem(MaterialCollections.getAllWoolColors().get(channel), "&bChannel ID: &3" + (channel + 1)));
menu.replaceExistingItem(slotCurrent, new CustomItem(ColoredMaterials.WOOL.get(channel), "&bChannel ID: &3" + (channel + 1)));
menu.addMenuClickHandler(slotCurrent, ChestMenuUtils.getEmptyClickHandler());
}

View File

@ -9,6 +9,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.DoubleRangeSetting;
import io.github.thebusybiscuit.slimefun4.core.attributes.Rechargeable;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.ArmorTask;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -40,7 +41,7 @@ public class SolarHelmet extends SlimefunItem {
throw new IllegalArgumentException("A Solar Helmet must have a positive charging level!");
}
charge = new ItemSetting<>("charge-amount", defaultChargingLevel);
charge = new DoubleRangeSetting("charge-amount", 0.01, defaultChargingLevel, Double.MAX_VALUE);
addItemSetting(charge);
}

View File

@ -5,6 +5,8 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
@ -144,18 +146,16 @@ public class AutoDisenchanter extends AContainer {
book.setItemMeta(meta);
}
private boolean isDisenchantable(ItemStack item) {
private boolean isDisenchantable(@Nullable ItemStack item) {
if (item == null) {
return false;
}
// stops endless checks of getByItem for books
else if (item.getType() != Material.BOOK) {
} else if (item.getType() != Material.BOOK) {
// ^ This stops endless checks of getByItem for books
SlimefunItem sfItem = SlimefunItem.getByItem(item);
return sfItem == null || sfItem.isDisenchantable();
} else {
return true;
}
}
@Override

View File

@ -36,6 +36,13 @@ import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
/**
* This class needs to be rewritten VERY BADLY.
* But we should focus on rewriting the recipe system first.
*
* @author TheBusyBiscuit
*
*/
public abstract class AutomatedCraftingChamber extends SlimefunItem implements InventoryBlock, EnergyNetComponent {
private final int[] border = { 0, 1, 3, 4, 5, 7, 8, 13, 14, 15, 16, 17, 50, 51, 52, 53 };
@ -233,11 +240,13 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
}
ItemStack item = menu.getItemInSlot(getInputSlots()[j]);
if (item != null && item.getAmount() == 1) {
if (craftLast)
if (craftLast) {
lastIteration = true;
else
} else {
return "";
}
}
builder.append(CustomItemSerializer.serialize(item, ItemFlag.MATERIAL, ItemFlag.ITEMMETA_DISPLAY_NAME, ItemFlag.ITEMMETA_LORE));
@ -248,8 +257,9 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
// we're only executing the last possible shaped recipe
// we don't want to allow this to be pressed instead of the default timer-based
// execution to prevent abuse and auto clickers
if (craftLast && !lastIteration)
if (craftLast && !lastIteration) {
return "";
}
return builder.toString();
}

View File

@ -1,19 +1,14 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines;
import java.util.EnumSet;
import java.util.Set;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.block.Block;
import org.bukkit.block.data.Ageable;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
@ -22,24 +17,11 @@ import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
public abstract class CropGrowthAccelerator extends AbstractGrowthAccelerator {
private final Set<Material> crops = EnumSet.noneOf(Material.class);
// We wanna strip the Slimefun Item id here
private static final ItemStack organicFertilizer = new ItemStackWrapper(SlimefunItems.FERTILIZER);
public CropGrowthAccelerator(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
crops.add(Material.WHEAT);
crops.add(Material.POTATOES);
crops.add(Material.CARROTS);
crops.add(Material.NETHER_WART);
crops.add(Material.BEETROOTS);
crops.add(Material.COCOA);
if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
crops.add(Material.SWEET_BERRY_BUSH);
}
}
public abstract int getEnergyConsumption();
@ -62,7 +44,7 @@ public abstract class CropGrowthAccelerator extends AbstractGrowthAccelerator {
for (int z = -getRadius(); z <= getRadius(); z++) {
Block block = b.getRelative(x, 0, z);
if (crops.contains(block.getType()) && grow(b, inv, block)) {
if (SlimefunTag.CROP_GROWTH_ACCELERATOR_BLOCKS.isTagged(block.getType()) && grow(b, inv, block)) {
return;
}
}

View File

@ -4,7 +4,7 @@ import org.bukkit.Material;
import org.bukkit.Tag;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
@ -22,7 +22,7 @@ public abstract class ElectrifiedCrucible extends AContainer {
registerRecipe(8, new ItemStack[] { new ItemStack(Material.BUCKET), new ItemStack(Material.TERRACOTTA, 12) }, new ItemStack[] { new ItemStack(Material.LAVA_BUCKET) });
registerRecipe(10, new ItemStack[] { new ItemStack(Material.BUCKET), new ItemStack(Material.OBSIDIAN) }, new ItemStack[] { new ItemStack(Material.LAVA_BUCKET) });
for (Material terracotta : MaterialCollections.getAllTerracottaColors().getAsArray()) {
for (Material terracotta : SlimefunTag.TERRACOTTA.getValues()) {
registerRecipe(8, new ItemStack[] { new ItemStack(Material.BUCKET), new ItemStack(terracotta, 12) }, new ItemStack[] { new ItemStack(Material.LAVA_BUCKET) });
}

View File

@ -0,0 +1,41 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.food;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.Optional;
/**
* This {@link SlimefunItem} can be obtained by crafting, it's
* used for various foods and recipes
*
* @author TheSilentPro
*/
public class HeavyCream extends SimpleSlimefunItem<ItemUseHandler> {
@ParametersAreNonnullByDefault
public HeavyCream(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
super(category, item, recipeType, recipe, recipeOutput);
}
@Nonnull
@Override
public ItemUseHandler getItemHandler() {
return e -> {
Optional<Block> block = e.getClickedBlock();
if (!block.isPresent() || !block.get().getType().isInteractable()) {
e.cancel();
}
};
}
}

View File

@ -3,6 +3,7 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.food;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemConsumptionHandler;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -20,7 +21,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
*/
public class MeatJerky extends SimpleSlimefunItem<ItemConsumptionHandler> {
private final ItemSetting<Integer> saturation = new ItemSetting<>("saturation-level", 6);
private final ItemSetting<Integer> saturation = new IntRangeSetting("saturation-level", 0, 6, Integer.MAX_VALUE);
public MeatJerky(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);

View File

@ -5,6 +5,7 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.DoubleRangeSetting;
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.UnplaceableBlock;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
@ -21,7 +22,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
*/
public class InfusedMagnet extends UnplaceableBlock {
private final ItemSetting<Double> radius = new ItemSetting<>("pickup-radius", 6.0);
private final ItemSetting<Double> radius = new DoubleRangeSetting("pickup-radius", 0.1, 6.0, Double.MAX_VALUE);
public InfusedMagnet(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);

View File

@ -53,10 +53,10 @@ public class MagicalZombiePills extends SimpleSlimefunItem<EntityInteractHandler
Player p = e.getPlayer();
if (entity instanceof ZombieVillager) {
useItem(p);
useItem(p, item);
healZombieVillager((ZombieVillager) entity, p);
} else if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_16) && entity instanceof PigZombie) {
useItem(p);
useItem(p, item);
healZombifiedPiglin((PigZombie) entity);
}
};
@ -71,7 +71,7 @@ public class MagicalZombiePills extends SimpleSlimefunItem<EntityInteractHandler
return PlayerRightClickEvent::cancel;
}
private void useItem(@Nonnull Player p) {
private void useItem(@Nonnull Player p, @Nonnull ItemStack item) {
if (p.getGameMode() != GameMode.CREATIVE) {
ItemUtils.consumeItem(item, false);
}

View File

@ -7,6 +7,7 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -24,7 +25,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
*/
public class TelepositionScroll extends SimpleSlimefunItem<ItemUseHandler> {
private final ItemSetting<Integer> radius = new ItemSetting<>("radius", 10);
private final ItemSetting<Integer> radius = new IntRangeSetting("radius", 1, 10, Integer.MAX_VALUE);
public TelepositionScroll(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);

View File

@ -12,6 +12,7 @@ import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.implementation.settings.TalismanEnchantment;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;

View File

@ -1,5 +1,9 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.medical;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Nonnull;
import org.bukkit.attribute.Attribute;
@ -16,12 +20,31 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public abstract class MedicalSupply<T extends ItemHandler> extends SimpleSlimefunItem<T> {
private final Set<PotionEffectType> curedEffects = new HashSet<>();
private final int healAmount;
public MedicalSupply(Category category, int healAmount, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
this.healAmount = healAmount;
curedEffects.add(PotionEffectType.POISON);
curedEffects.add(PotionEffectType.WITHER);
curedEffects.add(PotionEffectType.SLOW);
curedEffects.add(PotionEffectType.SLOW_DIGGING);
curedEffects.add(PotionEffectType.WEAKNESS);
curedEffects.add(PotionEffectType.CONFUSION);
curedEffects.add(PotionEffectType.BLINDNESS);
curedEffects.add(PotionEffectType.BAD_OMEN);
}
/**
* This returns the {@link PotionEffect PotionEffects} cured from this {@link MedicalSupply}.
*
* @return An immutable {@link Set} of cured {@link PotionEffect PotionEffects}
*/
public Set<PotionEffectType> getCuredEffects() {
return Collections.unmodifiableSet(curedEffects);
}
/**
@ -31,22 +54,11 @@ public abstract class MedicalSupply<T extends ItemHandler> extends SimpleSlimefu
* The {@link LivingEntity} to clear the effects from.
*/
public void clearNegativeEffects(@Nonnull LivingEntity n) {
if (n.hasPotionEffect(PotionEffectType.POISON))
n.removePotionEffect(PotionEffectType.POISON);
if (n.hasPotionEffect(PotionEffectType.WITHER))
n.removePotionEffect(PotionEffectType.WITHER);
if (n.hasPotionEffect(PotionEffectType.SLOW))
n.removePotionEffect(PotionEffectType.SLOW);
if (n.hasPotionEffect(PotionEffectType.SLOW_DIGGING))
n.removePotionEffect(PotionEffectType.SLOW_DIGGING);
if (n.hasPotionEffect(PotionEffectType.WEAKNESS))
n.removePotionEffect(PotionEffectType.WEAKNESS);
if (n.hasPotionEffect(PotionEffectType.CONFUSION))
n.removePotionEffect(PotionEffectType.CONFUSION);
if (n.hasPotionEffect(PotionEffectType.BLINDNESS))
n.removePotionEffect(PotionEffectType.BLINDNESS);
if (n.hasPotionEffect(PotionEffectType.BAD_OMEN))
n.removePotionEffect(PotionEffectType.BAD_OMEN);
for (PotionEffectType effect : curedEffects) {
if (n.hasPotionEffect(effect)) {
n.removePotionEffect(effect);
}
}
}
/**

View File

@ -4,6 +4,7 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable;
import io.github.thebusybiscuit.slimefun4.core.attributes.RandomMobDrop;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
@ -15,7 +16,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class BasicCircuitBoard extends SimpleSlimefunItem<ItemUseHandler> implements NotPlaceable, RandomMobDrop {
private final ItemSetting<Boolean> dropSetting = new ItemSetting<>("drop-from-golems", true);
private final ItemSetting<Integer> chance = new ItemSetting<>("golem-drop-chance", 75);
private final ItemSetting<Integer> chance = new IntRangeSetting("golem-drop-chance", 0, 75, 100);
public BasicCircuitBoard(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);

View File

@ -1,16 +1,24 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.misc;
import org.bukkit.Tag;
import org.bukkit.block.Block;
import org.bukkit.entity.Piglin;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.core.attributes.PiglinBarterDrop;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.VillagerRune;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import javax.annotation.Nonnull;
import java.util.Optional;
/**
* This {@link SlimefunItem} can only be obtained via bartering with a {@link Piglin}, its
* only current uses is the recipe for crafting the {@link VillagerRune}.
@ -21,9 +29,9 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
* @see PiglinBarterDrop
*
*/
public class StrangeNetherGoo extends SlimefunItem implements PiglinBarterDrop {
public class StrangeNetherGoo extends SimpleSlimefunItem<ItemUseHandler> implements PiglinBarterDrop {
private final ItemSetting<Integer> chance = new ItemSetting<>("barter-chance", 7);
private final ItemSetting<Integer> chance = new IntRangeSetting("barter-chance", 0, 7, 100);
public StrangeNetherGoo(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
@ -36,4 +44,16 @@ public class StrangeNetherGoo extends SlimefunItem implements PiglinBarterDrop {
return chance.getValue();
}
@Nonnull
@Override
public ItemUseHandler getItemHandler() {
return e -> {
Optional<Block> block = e.getClickedBlock();
if (block.isPresent() && Tag.SIGNS.isTagged(block.get().getType())) {
e.cancel();
}
};
}
}

View File

@ -23,6 +23,7 @@ import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.papermc.lib.PaperLib;
@ -33,7 +34,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class Smeltery extends AbstractSmeltery {
private final BlockFace[] faces = { BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST };
private final ItemSetting<Integer> fireBreakingChance = new ItemSetting<>("fire-breaking-chance", 34);
private final ItemSetting<Integer> fireBreakingChance = new IntRangeSetting("fire-breaking-chance", 0, 34, 100);
public Smeltery(Category category, SlimefunItemStack item) {
super(category, item, new ItemStack[] { null, new ItemStack(Material.NETHER_BRICK_FENCE), null, new ItemStack(Material.NETHER_BRICKS), new CustomItem(Material.DISPENSER, "Dispenser (Facing up)"), new ItemStack(Material.NETHER_BRICKS), null, new ItemStack(Material.FLINT_AND_STEEL), null }, BlockFace.DOWN);

View File

@ -7,7 +7,6 @@ import java.util.Map;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.Material;
@ -22,8 +21,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.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlockMachine;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
@ -209,14 +210,11 @@ public class IndustrialMiner extends MultiBlockMachine {
* @return Whether this {@link IndustrialMiner} is capable of mining this {@link Material}
*/
public boolean canMine(Material type) {
if (type.name().endsWith("_ORE")) {
if (SlimefunTag.INDUSTRIAL_MINER_ORES.isTagged(type)) {
return true;
} else if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_16)) {
if (type == Material.GILDED_BLACKSTONE) {
return true;
} else if (type == Material.ANCIENT_DEBRIS) {
return canMineAncientDebris.getValue();
}
return type == Material.ANCIENT_DEBRIS && canMineAncientDebris.getValue();
}
return false;

View File

@ -1,6 +1,7 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.tools;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.List;
@ -12,6 +13,7 @@ import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.GameMode;
@ -24,8 +26,6 @@ import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import io.github.thebusybiscuit.cscorelib2.config.Config;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.api.events.ClimbingPickLaunchEvent;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
@ -34,6 +34,8 @@ import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.implementation.settings.ClimbableSurface;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
@ -49,53 +51,110 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
*/
public class ClimbingPick extends SimpleSlimefunItem<ItemUseHandler> implements DamageableItem, RecipeDisplayItem {
private static final double BASE_POWER = 1;
private static final double STRONG_SURFACE_DEFAULT = 1.0;
private static final double WEAK_SURFACE_DEFAULT = 0.6;
private static final double MAX_DISTANCE = 4.4;
private static final double EFFICIENCY_MODIFIER = 0.125;
private static final long COOLDOWN = 4;
private final ItemSetting<Boolean> dualWielding = new ItemSetting<>("dual-wielding", true);
private final ItemSetting<Boolean> damageOnUse = new ItemSetting<>("damage-on-use", true);
private final Map<Material, Double> materialSpeeds;
private final Map<Material, ClimbableSurface> surfaces = new EnumMap<>(Material.class);
private final Set<UUID> users = new HashSet<>();
@ParametersAreNonnullByDefault
public ClimbingPick(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
addItemSetting(dualWielding, damageOnUse);
addDefaultSurfaces();
}
String cfgKey = getID() + ".launch-amounts.";
Config itemCfg = SlimefunPlugin.getItemCfg();
materialSpeeds = new EnumMap<>(Material.class);
for (Material mat : MaterialCollections.getAllIceBlocks()) {
materialSpeeds.put(mat, itemCfg.getOrSetDefault(cfgKey + mat.name(), 1.0));
/**
* This method adds every surface that is climbable by default.
*/
protected void addDefaultSurfaces() {
// These are "strong" surfaces, they will give you the biggest boost
for (Material surface : SlimefunTag.CLIMBING_PICK_STRONG_SURFACES.getValues()) {
addSurface(surface, STRONG_SURFACE_DEFAULT);
}
for (Material mat : MaterialCollections.getAllConcretePowderColors()) {
materialSpeeds.put(mat, itemCfg.getOrSetDefault(cfgKey + mat.name(), 1.0));
}
for (Material mat : MaterialCollections.getAllTerracottaColors()) {
materialSpeeds.put(mat, itemCfg.getOrSetDefault(cfgKey + mat.name(), 1.0));
}
materialSpeeds.put(Material.GRAVEL, itemCfg.getOrSetDefault(cfgKey + Material.GRAVEL.name(), 0.4));
materialSpeeds.put(Material.SAND, itemCfg.getOrSetDefault(cfgKey + Material.SAND.name(), 0.4));
materialSpeeds.put(Material.STONE, itemCfg.getOrSetDefault(cfgKey + Material.STONE.name(), 0.6));
materialSpeeds.put(Material.DIORITE, itemCfg.getOrSetDefault(cfgKey + Material.DIORITE.name(), 0.6));
materialSpeeds.put(Material.GRANITE, itemCfg.getOrSetDefault(cfgKey + Material.GRANITE.name(), 0.6));
materialSpeeds.put(Material.ANDESITE, itemCfg.getOrSetDefault(cfgKey + Material.ANDESITE.name(), 0.6));
materialSpeeds.put(Material.NETHERRACK, itemCfg.getOrSetDefault(cfgKey + Material.NETHERRACK.name(), 0.6));
if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_16)) {
materialSpeeds.put(Material.BLACKSTONE, itemCfg.getOrSetDefault(cfgKey + Material.BLACKSTONE.name(), 0.6));
materialSpeeds.put(Material.BASALT, itemCfg.getOrSetDefault(cfgKey + Material.BASALT.name(), 0.7));
// These are "weak" surfaces, you can still climb them but they don't have
// such a high boost as the "strong" surfaces
for (Material surface : SlimefunTag.CLIMBING_PICK_WEAK_SURFACES.getValues()) {
addSurface(surface, WEAK_SURFACE_DEFAULT);
}
}
protected void addSurface(@Nonnull Material type, double defaultValue) {
ClimbableSurface surface = new ClimbableSurface(type, defaultValue);
addItemSetting(surface);
surfaces.put(type, surface);
}
/**
* This returns whether the {@link ClimbingPick} needs to be held in both
* arms to work.
*
* @return Whether dual wielding is enabled
*/
public boolean isDualWieldingEnabled() {
return dualWielding.getValue();
}
/**
* This method returns a {@link Collection} of every {@link ClimbableSurface} the
* {@link ClimbingPick} can climb.
*
* @return A {@link Collection} of every {@link ClimbableSurface}
*/
@Nonnull
public Collection<ClimbableSurface> getClimbableSurfaces() {
return surfaces.values();
}
/**
* This returns the climbing speed for a given {@link Material}.
*
* @param type
* The {@link Material}
*
* @return The climbing speed for this {@link Material} or 0.
*/
public double getClimbingSpeed(@Nonnull Material type) {
Validate.notNull(type, "The surface cannot be null");
ClimbableSurface surface = surfaces.get(type);
if (surface != null) {
return surface.getValue();
} else {
return 0;
}
}
/**
* This returns the climbing speed for a given {@link Material} and the used {@link ItemStack}.
*
* @param item
* the {@link ClimbingPick}'s {@link ItemStack}
* @param type
* The {@link Material}
*
* @return The climbing speed or 0.
*/
public double getClimbingSpeed(@Nonnull ItemStack item, @Nonnull Material type) {
double speed = getClimbingSpeed(type);
if (speed > 0) {
int efficiencyLevel = item.getEnchantmentLevel(Enchantment.DIG_SPEED);
if (efficiencyLevel > 0) {
speed += efficiencyLevel * EFFICIENCY_MODIFIER;
}
}
return speed;
}
@Override
public ItemUseHandler getItemHandler() {
return e -> {
@ -106,7 +165,7 @@ public class ClimbingPick extends SimpleSlimefunItem<ItemUseHandler> implements
Block block = e.getClickedBlock().get();
Player p = e.getPlayer();
// Check if the Player is standing close to the wall
// Check if the Player is standing close enough to the wall
if (p.getLocation().distanceSquared(block.getLocation().add(0.5, 0.5, 0.5)) > MAX_DISTANCE) {
return;
}
@ -118,11 +177,9 @@ public class ClimbingPick extends SimpleSlimefunItem<ItemUseHandler> implements
}
// Top and bottom faces won't be allowed
if (e.getClickedFace() == BlockFace.DOWN || e.getClickedFace() == BlockFace.UP) {
return;
if (e.getClickedFace() != BlockFace.DOWN && e.getClickedFace() != BlockFace.UP) {
climb(p, e.getHand(), e.getItem(), block);
}
climb(p, e.getHand(), e.getItem(), block);
};
}
@ -138,19 +195,13 @@ public class ClimbingPick extends SimpleSlimefunItem<ItemUseHandler> implements
@ParametersAreNonnullByDefault
private void climb(Player p, EquipmentSlot hand, ItemStack item, Block block) {
double power = materialSpeeds.getOrDefault(block.getType(), 0.0);
double power = getClimbingSpeed(item, block.getType());
if (power > 0.05) {
// Prevent players from spamming this
// Prevent players from spamming this item by enforcing a cooldown
if (users.add(p.getUniqueId())) {
int efficiencyLevel = item.getEnchantmentLevel(Enchantment.DIG_SPEED);
if (efficiencyLevel != 0) {
power += efficiencyLevel * 0.1;
}
SlimefunPlugin.runSync(() -> users.remove(p.getUniqueId()), 4L);
Vector velocity = new Vector(0, power * BASE_POWER, 0);
SlimefunPlugin.runSync(() -> users.remove(p.getUniqueId()), COOLDOWN);
Vector velocity = new Vector(0, power, 0);
ClimbingPickLaunchEvent event = new ClimbingPickLaunchEvent(p, velocity, this, item, block);
Bukkit.getPluginManager().callEvent(event);
@ -215,7 +266,7 @@ public class ClimbingPick extends SimpleSlimefunItem<ItemUseHandler> implements
public List<ItemStack> getDisplayRecipes() {
List<ItemStack> display = new ArrayList<>();
for (Material mat : materialSpeeds.keySet()) {
for (Material mat : surfaces.keySet()) {
display.add(new ItemStack(mat));
}

View File

@ -4,9 +4,9 @@ import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialTools;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
@ -29,7 +29,7 @@ public class ExplosiveShovel extends ExplosiveTool {
@Override
protected boolean canBreak(Player p, Block b) {
return MaterialTools.getBreakableByShovel().contains(b.getType()) && SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.BREAK_BLOCK);
return SlimefunTag.EXPLOSIVE_SHOVEL_BLOCKS.isTagged(b.getType()) && SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.BREAK_BLOCK);
}
}

View File

@ -13,7 +13,6 @@ import org.bukkit.event.block.BlockExplodeEvent;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.core.attributes.DamageableItem;
@ -21,6 +20,7 @@ import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable;
import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler;
@ -111,7 +111,7 @@ class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements NotPla
protected boolean canBreak(Player p, Block b) {
if (b.isEmpty() || b.isLiquid()) {
return false;
} else if (MaterialCollections.getAllUnbreakableBlocks().contains(b.getType())) {
} else if (SlimefunTag.UNBREAKABLE_MATERIALS.isTagged(b.getType())) {
return false;
} else if (!b.getWorld().getWorldBorder().isInside(b.getLocation())) {
return false;

View File

@ -6,9 +6,13 @@ import java.util.List;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Effect;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.ItemFrame;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.collections.RandomizedSet;
@ -43,6 +47,7 @@ public class GoldPan extends SimpleSlimefunItem<ItemUseHandler> implements Recip
private final RandomizedSet<ItemStack> randomizer = new RandomizedSet<>();
private final Set<GoldPanDrop> drops = new HashSet<>();
@ParametersAreNonnullByDefault
public GoldPan(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
@ -51,7 +56,13 @@ public class GoldPan extends SimpleSlimefunItem<ItemUseHandler> implements Recip
addItemHandler(onEntityInteract());
}
protected Material getInput() {
/**
* This method returns the target {@link Material} for this {@link GoldPan}.
*
* @return The {@link Material} this {@link GoldPan} can be used on
*/
@Nonnull
protected Material getTargetMaterial() {
return Material.GRAVEL;
}
@ -84,6 +95,13 @@ public class GoldPan extends SimpleSlimefunItem<ItemUseHandler> implements Recip
}
}
/**
* This returns a random output {@link ItemStack} that can be obtained via
* this {@link GoldPan}.
*
* @return a random {@link ItemStack} obtained by this {@link GoldPan}
*/
@Nonnull
public ItemStack getRandomOutput() {
return randomizer.getRandom();
}
@ -101,7 +119,7 @@ public class GoldPan extends SimpleSlimefunItem<ItemUseHandler> implements Recip
if (block.isPresent()) {
Block b = block.get();
if (b.getType() == getInput() && SlimefunPlugin.getProtectionManager().hasPermission(e.getPlayer(), b.getLocation(), ProtectableAction.BREAK_BLOCK)) {
if (b.getType() == getTargetMaterial() && SlimefunPlugin.getProtectionManager().hasPermission(e.getPlayer(), b.getLocation(), ProtectableAction.BREAK_BLOCK)) {
ItemStack output = getRandomOutput();
b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getType());
@ -124,7 +142,11 @@ public class GoldPan extends SimpleSlimefunItem<ItemUseHandler> implements Recip
* @return the {@link EntityInteractHandler} of this {@link SlimefunItem}
*/
public EntityInteractHandler onEntityInteract() {
return (e, item, offHand) -> e.setCancelled(true);
return (e, item, offHand) -> {
if (!(e.getRightClicked() instanceof ItemFrame)) {
e.setCancelled(true);
}
};
}
@Override
@ -133,7 +155,7 @@ public class GoldPan extends SimpleSlimefunItem<ItemUseHandler> implements Recip
for (GoldPanDrop drop : drops) {
if (drop.getValue() > 0) {
recipes.add(new ItemStack(getInput()));
recipes.add(new ItemStack(getTargetMaterial()));
recipes.add(drop.getOutput());
}
}

View File

@ -16,6 +16,7 @@ import org.bukkit.util.Vector;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
@ -38,7 +39,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class GrapplingHook extends SimpleSlimefunItem<ItemUseHandler> {
private final ItemSetting<Boolean> consumeOnUse = new ItemSetting<>("consume-on-use", true);
private final ItemSetting<Integer> despawnTicks = new ItemSetting<>("despawn-seconds", 60);
private final ItemSetting<Integer> despawnTicks = new IntRangeSetting("despawn-seconds", 0, 60, Integer.MAX_VALUE);
@ParametersAreNonnullByDefault
public GrapplingHook(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {

View File

@ -12,7 +12,6 @@ import org.bukkit.block.data.Orientable;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.blocks.Vein;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
@ -49,7 +48,7 @@ public class LumberAxe extends SimpleSlimefunItem<ItemUseHandler> implements Not
private ToolUseHandler onBlockBreak() {
return (e, tool, fortune, drops) -> {
if (MaterialCollections.getAllLogs().contains(e.getBlock().getType())) {
if (Tag.LOGS.isTagged(e.getBlock().getType())) {
List<Block> logs = Vein.find(e.getBlock(), MAX_BROKEN, b -> Tag.LOGS.isTagged(b.getType()));
if (logs.contains(e.getBlock())) {

View File

@ -17,7 +17,7 @@ public class NetherGoldPan extends GoldPan {
}
@Override
protected Material getInput() {
protected Material getTargetMaterial() {
return Material.SOUL_SAND;
}

View File

@ -1,24 +1,41 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.tools;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.Event.Result;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
import io.github.thebusybiscuit.slimefun4.core.attributes.DamageableItem;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
* The {@link PickaxeOfTheSeeker} will make you face the nearest ore upon right clicking.
*
* @author TheBusyBiscuit
*
*/
public class PickaxeOfTheSeeker extends SimpleSlimefunItem<ItemUseHandler> implements DamageableItem {
private final ItemSetting<Integer> maxRange = new IntRangeSetting("max-range", 1, 5, Integer.MAX_VALUE);
@ParametersAreNonnullByDefault
public PickaxeOfTheSeeker(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
addItemSetting(maxRange);
}
@Override
@ -42,21 +59,35 @@ public class PickaxeOfTheSeeker extends SimpleSlimefunItem<ItemUseHandler> imple
float yaw = alpha2 > 90 ? (180 - alpha1) : alpha1;
float pitch = (float) ((-Math.atan((closest.getY() - 0.5 - p.getLocation().getY()) / Math.sqrt(l * l + w * w))) * 180 / Math.PI);
p.teleport(new Location(p.getWorld(), p.getLocation().getX(), p.getLocation().getY(), p.getLocation().getZ(), yaw, pitch));
// We could teleport them asynchronously here...
// But we're only changing the pitch and yaw anyway.
Location loc = new Location(p.getWorld(), p.getLocation().getX(), p.getLocation().getY(), p.getLocation().getZ(), yaw, pitch);
p.teleport(loc);
}
damageItem(p, e.getItem());
};
}
private Block findClosestOre(Player p) {
@Nullable
private Block findClosestOre(@Nonnull Player p) {
Block start = p.getLocation().getBlock();
Block closest = null;
double lastDistance = Double.MAX_VALUE;
int range = maxRange.getValue();
for (int x = -4; x <= 4; x++) {
for (int y = -4; y <= 4; y++) {
for (int z = -4; z <= 4; z++) {
if (MaterialCollections.getAllOres().contains(p.getLocation().add(x, y, z).getBlock().getType()) && (closest == null || p.getLocation().distanceSquared(closest.getLocation()) > p.getLocation().distanceSquared(p.getLocation().add(x, y, z)))) {
closest = p.getLocation().getBlock().getRelative(x, y, z);
for (int x = -range; x <= range; x++) {
for (int y = -range; y <= range; y++) {
for (int z = -range; z <= range; z++) {
Block block = start.getRelative(x, y, z);
if (SlimefunTag.PICKAXE_OF_THE_SEEKER_BLOCKS.isTagged(block.getType())) {
double distance = block.getLocation().distanceSquared(start.getLocation());
if (closest == null || distance < lastDistance) {
closest = block;
lastDistance = distance;
}
}
}
}

View File

@ -2,6 +2,8 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.tools;
import java.util.List;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Effect;
import org.bukkit.Material;
import org.bukkit.block.Block;
@ -11,12 +13,13 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.blocks.Vein;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
@ -31,32 +34,25 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
*/
public class PickaxeOfVeinMining extends SimpleSlimefunItem<ToolUseHandler> {
private final ItemSetting<Integer> maxBlocks = new ItemSetting<Integer>("max-blocks", 16) {
@Override
public boolean validateInput(Integer input) {
// We do not wanna allow any negative values here
return super.validateInput(input) && input.intValue() > 0;
}
};
private final ItemSetting<Integer> maxBlocks = new IntRangeSetting("max-blocks", 1, 16, Integer.MAX_VALUE);
@ParametersAreNonnullByDefault
public PickaxeOfVeinMining(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
addItemSetting(maxBlocks);
}
@Override
public ToolUseHandler getItemHandler() {
return (e, tool, fortune, drops) -> {
if (MaterialCollections.getAllOres().contains(e.getBlock().getType())) {
List<Block> blocks = Vein.find(e.getBlock(), maxBlocks.getValue(), MaterialCollections.getAllOres());
if (SlimefunTag.PICKAXE_OF_VEIN_MINING_BLOCKS.isTagged(e.getBlock().getType())) {
List<Block> blocks = Vein.find(e.getBlock(), maxBlocks.getValue(), b -> SlimefunTag.PICKAXE_OF_VEIN_MINING_BLOCKS.isTagged(b.getType()));
breakBlocks(e.getPlayer(), blocks, fortune, tool);
}
};
}
@ParametersAreNonnullByDefault
private void breakBlocks(Player p, List<Block> blocks, int fortune, ItemStack tool) {
for (Block b : blocks) {
if (SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.BREAK_BLOCK)) {
@ -65,7 +61,6 @@ public class PickaxeOfVeinMining extends SimpleSlimefunItem<ToolUseHandler> {
if (tool.containsEnchantment(Enchantment.SILK_TOUCH)) {
b.getWorld().dropItemNaturally(b.getLocation(), new ItemStack(b.getType()));
} else {
for (ItemStack drop : b.getDrops(tool)) {
b.getWorld().dropItemNaturally(b.getLocation(), drop.getType().isBlock() ? drop : new CustomItem(drop, fortune));
}

View File

@ -3,23 +3,32 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.tools;
import java.util.Collection;
import java.util.Optional;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Effect;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.slimefun4.core.attributes.DamageableItem;
import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
* The {@link SmeltersPickaxe} automatically smelts any ore you mine.
*
* @author TheBusyBiscuit
*
*/
public class SmeltersPickaxe extends SimpleSlimefunItem<ToolUseHandler> implements DamageableItem {
@ParametersAreNonnullByDefault
public SmeltersPickaxe(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
}
@ -27,12 +36,14 @@ public class SmeltersPickaxe extends SimpleSlimefunItem<ToolUseHandler> implemen
@Override
public ToolUseHandler getItemHandler() {
return (e, tool, fortune, drops) -> {
if (MaterialCollections.getAllOres().contains(e.getBlock().getType()) && !BlockStorage.hasBlockInfo(e.getBlock())) {
Collection<ItemStack> blockDrops = e.getBlock().getDrops(getItem());
Block b = e.getBlock();
if (SlimefunTag.SMELTERS_PICKAXE_BLOCKS.isTagged(b.getType()) && !BlockStorage.hasBlockInfo(b)) {
Collection<ItemStack> blockDrops = b.getDrops(getItem());
for (ItemStack drop : blockDrops) {
if (drop != null && drop.getType() != Material.AIR) {
smelt(e.getBlock(), drop, fortune);
smelt(b, drop, fortune);
drops.add(drop);
}
}
@ -42,6 +53,7 @@ public class SmeltersPickaxe extends SimpleSlimefunItem<ToolUseHandler> implemen
};
}
@ParametersAreNonnullByDefault
private void smelt(Block b, ItemStack drop, int fortune) {
Optional<ItemStack> furnaceOutput = SlimefunPlugin.getMinecraftRecipeService().getFurnaceOutput(drop);

View File

@ -2,6 +2,7 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.tools;
import java.text.DecimalFormat;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.UUID;
import javax.annotation.Nonnull;
@ -9,6 +10,7 @@ import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.Sound;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@ -77,9 +79,20 @@ public class TapeMeasure extends SimpleSlimefunItem<ItemUseHandler> implements N
item.setItemMeta(meta);
}
@ParametersAreNonnullByDefault
private void measure(Player p, ItemStack item, Block block) {
OptionalDouble distance = getDistance(p, item, block);
if (distance.isPresent()) {
p.playSound(block.getLocation(), Sound.ITEM_BOOK_PUT, 1, 0.7F);
String label = format.format(distance.getAsDouble());
SlimefunPlugin.getLocalization().sendMessage(p, "messages.tape-measure.distance", msg -> msg.replace("%distance%", label));
}
}
@Nonnull
@ParametersAreNonnullByDefault
private Optional<Location> getAnchor(Player p, ItemStack item) {
public Optional<Location> getAnchor(Player p, ItemStack item) {
ItemMeta meta = item.getItemMeta();
String data = meta.getPersistentDataContainer().get(key, PersistentDataType.STRING);
@ -106,13 +119,14 @@ public class TapeMeasure extends SimpleSlimefunItem<ItemUseHandler> implements N
}
@ParametersAreNonnullByDefault
private void measure(Player p, ItemStack item, Block block) {
public OptionalDouble getDistance(Player p, ItemStack item, Block block) {
Optional<Location> anchor = getAnchor(p, item);
if (anchor.isPresent()) {
Location loc = anchor.get();
double distance = loc.distance(block.getLocation());
SlimefunPlugin.getLocalization().sendMessage(p, "messages.tape-measure.distance", msg -> msg.replace("%distance%", format.format(distance)));
return OptionalDouble.of(loc.distance(block.getLocation()));
} else {
return OptionalDouble.empty();
}
}

View File

@ -1,5 +1,7 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.weapons;
import java.util.Collection;
import org.bukkit.Bukkit;
import org.bukkit.Particle;
import org.bukkit.Sound;
@ -11,12 +13,11 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
import io.github.thebusybiscuit.slimefun4.core.handlers.BowShootHandler;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import java.util.Collection;
/**
* The {@link ExplosiveBow} is a {@link SlimefunBow} which creates a fake explosion when it hits
* a {@link LivingEntity}. Any nearby {@link LivingEntity LivingEntities} get pushed away and
@ -30,14 +31,7 @@ import java.util.Collection;
*/
public class ExplosiveBow extends SlimefunBow {
private final ItemSetting<Integer> range = new ItemSetting<Integer>("explosion-range", 3) {
@Override
public boolean validateInput(Integer input) {
return super.validateInput(input) && input > 0;
}
};
private final ItemSetting<Integer> range = new IntRangeSetting("explosion-range", 1, 3, Integer.MAX_VALUE);
public ExplosiveBow(Category category, SlimefunItemStack item, ItemStack[] recipe) {
super(category, item, recipe);

View File

@ -14,6 +14,7 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
import io.github.thebusybiscuit.slimefun4.core.handlers.EntityKillHandler;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -22,11 +23,11 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class SwordOfBeheading extends SimpleSlimefunItem<EntityKillHandler> {
private final ItemSetting<Integer> chanceZombie = new ItemSetting<>("chance.ZOMBIE", 40);
private final ItemSetting<Integer> chanceSkeleton = new ItemSetting<>("chance.SKELETON", 40);
private final ItemSetting<Integer> chanceWitherSkeleton = new ItemSetting<>("chance.WITHER_SKELETON", 25);
private final ItemSetting<Integer> chanceCreeper = new ItemSetting<>("chance.CREEPER", 40);
private final ItemSetting<Integer> chancePlayer = new ItemSetting<>("chance.PLAYER", 70);
private final ItemSetting<Integer> chanceZombie = new IntRangeSetting("chance.ZOMBIE", 0, 40, 100);
private final ItemSetting<Integer> chanceSkeleton = new IntRangeSetting("chance.SKELETON", 0, 40, 100);
private final ItemSetting<Integer> chanceWitherSkeleton = new IntRangeSetting("chance.WITHER_SKELETON", 0, 25, 100);
private final ItemSetting<Integer> chanceCreeper = new IntRangeSetting("chance.CREEPER", 0, 40, 100);
private final ItemSetting<Integer> chancePlayer = new IntRangeSetting("chance.PLAYER", 0, 70, 100);
public SwordOfBeheading(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);

View File

@ -7,6 +7,7 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.VampireBladeListener;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
@ -25,7 +26,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class VampireBlade extends SlimefunItem {
private static final double HEALING_AMOUNT = 4.0;
private final ItemSetting<Integer> chance = new ItemSetting<>("chance", 45);
private final ItemSetting<Integer> chance = new IntRangeSetting("chance", 0, 45, 100);
public VampireBlade(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);

View File

@ -1,11 +1,9 @@
package io.github.thebusybiscuit.slimefun4.implementation.listeners;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.Nonnull;
@ -13,7 +11,6 @@ import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.Material;
import org.bukkit.Tag;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.enchantments.Enchantment;
@ -30,6 +27,7 @@ import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason;
@ -49,21 +47,11 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
*/
public class BlockListener implements Listener {
// Materials that require a Block under it, e.g. Pressure Plates
private final Set<Material> sensitiveMaterials = EnumSet.noneOf(Material.class);
public BlockListener(@Nonnull SlimefunPlugin plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
sensitiveMaterials.add(Material.CAKE);
sensitiveMaterials.add(Material.STONE_PRESSURE_PLATE);
sensitiveMaterials.add(Material.LIGHT_WEIGHTED_PRESSURE_PLATE);
sensitiveMaterials.add(Material.HEAVY_WEIGHTED_PRESSURE_PLATE);
sensitiveMaterials.addAll(Tag.SAPLINGS.getValues());
sensitiveMaterials.addAll(Tag.WOODEN_PRESSURE_PLATES.getValues());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onBlockPlace(BlockPlaceEvent e) {
if (BlockStorage.hasBlockInfo(e.getBlock())) {
e.setCancelled(true);
@ -87,7 +75,7 @@ public class BlockListener implements Listener {
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent e) {
checkForSensitiveBlockAbove(e.getPlayer(), e.getBlock());
@ -175,7 +163,7 @@ public class BlockListener implements Listener {
private void checkForSensitiveBlockAbove(Player p, Block b) {
Block blockAbove = b.getRelative(BlockFace.UP);
if (sensitiveMaterials.contains(blockAbove.getType())) {
if (SlimefunTag.SENSITIVE_MATERIALS.isTagged(blockAbove.getType())) {
SlimefunItem sfItem = BlockStorage.check(blockAbove);
if (sfItem != null && !sfItem.useVanillaBlockBreaking()) {

View File

@ -4,7 +4,6 @@ import javax.annotation.Nonnull;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Tag;
import org.bukkit.block.Block;
import org.bukkit.block.data.type.Piston;
import org.bukkit.entity.EntityType;
@ -21,6 +20,7 @@ import org.bukkit.event.player.PlayerBucketEmptyEvent;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
/**
@ -85,12 +85,8 @@ public class BlockPhysicsListener implements Listener {
public void onLiquidFlow(BlockFromToEvent e) {
Block block = e.getToBlock();
if (block.getType() == Material.PLAYER_HEAD || block.getType() == Material.PLAYER_WALL_HEAD || Tag.SAPLINGS.isTagged(block.getType())) {
String item = BlockStorage.checkID(block);
if (item != null) {
e.setCancelled(true);
}
if (SlimefunTag.FLUID_SENSITIVE_MATERIALS.isTagged(block.getType()) && BlockStorage.hasBlockInfo(block)) {
e.setCancelled(true);
}
}

View File

@ -56,7 +56,8 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.MagicianTalisman;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.Talisman;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.TalismanEnchantment;
import io.github.thebusybiscuit.slimefun4.implementation.settings.TalismanEnchantment;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
public class TalismanListener implements Listener {
@ -300,8 +301,8 @@ public class TalismanListener implements Listener {
@EventHandler
public void onBlockBreak(BlockBreakEvent e) {
if (e.getBlock().getType().name().endsWith("_ORE")) {
Talisman.tryActivate(e, SlimefunItems.TALISMAN_CAVEMAN);
if (SlimefunTag.CAVEMAN_TALISMAN_TRIGGERS.isTagged(e.getBlock().getType())) {
Talisman.tryActivate(e, SlimefunItems.TALISMAN_WISE);
}
}

View File

@ -0,0 +1,48 @@
package io.github.thebusybiscuit.slimefun4.implementation.settings;
import javax.annotation.Nonnull;
import org.bukkit.Material;
import io.github.thebusybiscuit.slimefun4.api.events.ClimbingPickLaunchEvent;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.settings.DoubleRangeSetting;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ClimbingPick;
/**
* This is an {@link ItemSetting}
*
* @author TheBusyBiscuit
*
* @see ClimbingPick
* @see ClimbingPickLaunchEvent
*
*/
public class ClimbableSurface extends DoubleRangeSetting {
private final Material type;
/**
* This creates a new {@link ClimbableSurface} for the given {@link Material}.
*
* @param surface
* The {@link Material} of this surface
* @param defaultValue
* The default launch amount
*/
public ClimbableSurface(@Nonnull Material surface, double defaultValue) {
super("launch-amounts." + surface.name(), 0, defaultValue, Double.MAX_VALUE);
this.type = surface;
}
/**
* This returns the {@link Material} of this surface.
*
* @return The {@link Material} of this surface
*/
@Nonnull
public Material getType() {
return type;
}
}

View File

@ -1,8 +1,11 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans;
package io.github.thebusybiscuit.slimefun4.implementation.settings;
import javax.annotation.Nonnull;
import org.bukkit.enchantments.Enchantment;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.implementation.items.magical.talismans.MagicianTalisman;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.TalismanListener;
/**
@ -17,7 +20,7 @@ public class TalismanEnchantment extends ItemSetting<Boolean> {
private final Enchantment enchantment;
private final int level;
public TalismanEnchantment(Enchantment enchantment, int level) {
public TalismanEnchantment(@Nonnull Enchantment enchantment, int level) {
super("allow-enchantments." + enchantment.getKey().getKey() + ".level." + level, true);
this.enchantment = enchantment;
@ -29,6 +32,7 @@ public class TalismanEnchantment extends ItemSetting<Boolean> {
*
* @return The associated {@link Enchantment}
*/
@Nonnull
public Enchantment getEnchantment() {
return enchantment;
}

View File

@ -0,0 +1,6 @@
/**
* This package holds implementations of {@link io.github.thebusybiscuit.slimefun4.api.items.ItemSetting} that are for
* very specific {@link me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem SlimefunItems} and generally not
* very useful out of their context.
*/
package io.github.thebusybiscuit.slimefun4.implementation.settings;

View File

@ -47,7 +47,6 @@ public final class PostSetup {
public static void setupWiki() {
Slimefun.getLogger().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))) {

View File

@ -16,7 +16,6 @@ import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionType;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.core.attributes.Radioactivity;
@ -116,6 +115,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.food.Juice;
import io.github.thebusybiscuit.slimefun4.implementation.items.food.MagicSugar;
import io.github.thebusybiscuit.slimefun4.implementation.items.food.MeatJerky;
import io.github.thebusybiscuit.slimefun4.implementation.items.food.MonsterJerky;
import io.github.thebusybiscuit.slimefun4.implementation.items.food.HeavyCream;
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;
@ -190,6 +190,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.weapons.IcyBow;
import io.github.thebusybiscuit.slimefun4.implementation.items.weapons.SeismicAxe;
import io.github.thebusybiscuit.slimefun4.implementation.items.weapons.SwordOfBeheading;
import io.github.thebusybiscuit.slimefun4.implementation.items.weapons.VampireBlade;
import io.github.thebusybiscuit.slimefun4.utils.ColoredMaterials;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -917,7 +918,7 @@ public final class SlimefunItemSetup {
new ItemStack[] {new ItemStack(Material.SAND, 2), null, null, null, null, null, null, null, null})
.register(plugin);
new SlimefunItem(categories.misc, SlimefunItems.HEAVY_CREAM, RecipeType.ENHANCED_CRAFTING_TABLE,
new HeavyCream(categories.misc, SlimefunItems.HEAVY_CREAM, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {new ItemStack(Material.MILK_BUCKET), null, null, null, null, null, null, null, null},
new SlimefunItemStack(SlimefunItems.HEAVY_CREAM, 2))
.register(plugin);
@ -1997,11 +1998,6 @@ public final class SlimefunItemSetup {
new ItemStack[]{null, null, null, SlimefunItems.HEATING_COIL, new ItemStack(Material.SMOKER), SlimefunItems.HEATING_COIL, null, new ItemStack(Material.CAMPFIRE), null})
.register(plugin);
}
else {
new AutoDrier(categories.electricity, SlimefunItems.AUTO_DRIER, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[]{null, null, null, SlimefunItems.HEATING_COIL, new ItemStack(Material.FURNACE), SlimefunItems.HEATING_COIL, null, new ItemStack(Material.TORCH), null})
.register(plugin);
}
new AutoBrewer(categories.electricity, SlimefunItems.AUTO_BREWER, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {null, SlimefunItems.HEATING_COIL, null, SlimefunItems.REINFORCED_PLATE, new ItemStack(Material.BREWING_STAND), SlimefunItems.REINFORCED_PLATE, null, SlimefunItems.ELECTRIC_MOTOR, null}) {
@ -2328,32 +2324,32 @@ public final class SlimefunItemSetup {
new RainbowBlock(categories.magicalGadgets, SlimefunItems.RAINBOW_WOOL, RecipeType.ANCIENT_ALTAR,
new ItemStack[] {new ItemStack(Material.WHITE_WOOL), new ItemStack(Material.WHITE_WOOL), new ItemStack(Material.WHITE_WOOL), new ItemStack(Material.WHITE_WOOL), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_WOOL), new ItemStack(Material.WHITE_WOOL), new ItemStack(Material.WHITE_WOOL), new ItemStack(Material.WHITE_WOOL)},
new SlimefunItemStack(SlimefunItems.RAINBOW_WOOL, 8), new RainbowTickHandler(MaterialCollections.getAllWoolColors()))
new SlimefunItemStack(SlimefunItems.RAINBOW_WOOL, 8), new RainbowTickHandler(ColoredMaterials.WOOL))
.register(plugin);
new RainbowBlock(categories.magicalGadgets, SlimefunItems.RAINBOW_GLASS, RecipeType.ANCIENT_ALTAR,
new ItemStack[] {new ItemStack(Material.WHITE_STAINED_GLASS), new ItemStack(Material.WHITE_STAINED_GLASS), new ItemStack(Material.WHITE_STAINED_GLASS), new ItemStack(Material.WHITE_STAINED_GLASS), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_STAINED_GLASS), new ItemStack(Material.WHITE_STAINED_GLASS), new ItemStack(Material.WHITE_STAINED_GLASS), new ItemStack(Material.WHITE_STAINED_GLASS)},
new SlimefunItemStack(SlimefunItems.RAINBOW_GLASS, 8), new RainbowTickHandler(MaterialCollections.getAllStainedGlassColors()))
new SlimefunItemStack(SlimefunItems.RAINBOW_GLASS, 8), new RainbowTickHandler(ColoredMaterials.STAINED_GLASS))
.register(plugin);
new RainbowBlock(categories.magicalGadgets, SlimefunItems.RAINBOW_GLASS_PANE, RecipeType.ANCIENT_ALTAR,
new ItemStack[] {new ItemStack(Material.WHITE_STAINED_GLASS_PANE), new ItemStack(Material.WHITE_STAINED_GLASS_PANE), new ItemStack(Material.WHITE_STAINED_GLASS_PANE), new ItemStack(Material.WHITE_STAINED_GLASS_PANE), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_STAINED_GLASS_PANE), new ItemStack(Material.WHITE_STAINED_GLASS_PANE), new ItemStack(Material.WHITE_STAINED_GLASS_PANE), new ItemStack(Material.WHITE_STAINED_GLASS_PANE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_GLASS_PANE, 8), new RainbowTickHandler(MaterialCollections.getAllStainedGlassPaneColors()))
new SlimefunItemStack(SlimefunItems.RAINBOW_GLASS_PANE, 8), new RainbowTickHandler(ColoredMaterials.STAINED_GLASS_PANE))
.register(plugin);
new RainbowBlock(categories.magicalGadgets, SlimefunItems.RAINBOW_CLAY, RecipeType.ANCIENT_ALTAR,
new ItemStack[] {new ItemStack(Material.WHITE_TERRACOTTA), new ItemStack(Material.WHITE_TERRACOTTA), new ItemStack(Material.WHITE_TERRACOTTA), new ItemStack(Material.WHITE_TERRACOTTA), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_TERRACOTTA), new ItemStack(Material.WHITE_TERRACOTTA), new ItemStack(Material.WHITE_TERRACOTTA), new ItemStack(Material.WHITE_TERRACOTTA)},
new SlimefunItemStack(SlimefunItems.RAINBOW_CLAY, 8), new RainbowTickHandler(MaterialCollections.getAllTerracottaColors()))
new SlimefunItemStack(SlimefunItems.RAINBOW_CLAY, 8), new RainbowTickHandler(ColoredMaterials.TERRACOTTA))
.register(plugin);
new RainbowBlock(categories.magicalGadgets, SlimefunItems.RAINBOW_CONCRETE, RecipeType.ANCIENT_ALTAR,
new ItemStack[] {new ItemStack(Material.WHITE_CONCRETE), new ItemStack(Material.WHITE_CONCRETE), new ItemStack(Material.WHITE_CONCRETE), new ItemStack(Material.WHITE_CONCRETE), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_CONCRETE), new ItemStack(Material.WHITE_CONCRETE), new ItemStack(Material.WHITE_CONCRETE), new ItemStack(Material.WHITE_CONCRETE)},
new SlimefunItemStack(SlimefunItems.RAINBOW_CONCRETE, 8), new RainbowTickHandler(MaterialCollections.getAllConcreteColors()))
new SlimefunItemStack(SlimefunItems.RAINBOW_CONCRETE, 8), new RainbowTickHandler(ColoredMaterials.CONCRETE))
.register(plugin);
new RainbowBlock(categories.magicalGadgets, SlimefunItems.RAINBOW_GLAZED_TERRACOTTA, RecipeType.ANCIENT_ALTAR,
new ItemStack[] {new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), SlimefunItems.RAINBOW_RUNE, new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), new ItemStack(Material.WHITE_GLAZED_TERRACOTTA), new ItemStack(Material.WHITE_GLAZED_TERRACOTTA)},
new SlimefunItemStack(SlimefunItems.RAINBOW_GLAZED_TERRACOTTA, 8), new RainbowTickHandler(MaterialCollections.getAllGlazedTerracottaColors()))
new SlimefunItemStack(SlimefunItems.RAINBOW_GLAZED_TERRACOTTA, 8), new RainbowTickHandler(ColoredMaterials.GLAZED_TERRACOTTA))
.register(plugin);
// Christmas

View File

@ -0,0 +1,160 @@
package io.github.thebusybiscuit.slimefun4.utils;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.bukkit.Material;
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
/**
* This class holds a few ordered {@link List Lists} that hold colored variants
* of {@link Material}.
*
* @author TheBusyBiscuit
*
* @see SlimefunTag
*
*/
public final class ColoredMaterials {
/**
* We don't want any instances of this class, so we set the
* constructor to be private.
*/
private ColoredMaterials() {}
/**
* This {@link List} contains all wool colors ordered by their appearance ingame.
*/
public static final List<Material> WOOL = Collections.unmodifiableList(Arrays.asList(
Material.WHITE_WOOL,
Material.ORANGE_WOOL,
Material.MAGENTA_WOOL,
Material.LIGHT_BLUE_WOOL,
Material.YELLOW_WOOL,
Material.LIME_WOOL,
Material.PINK_WOOL,
Material.GRAY_WOOL,
Material.LIGHT_GRAY_WOOL,
Material.CYAN_WOOL,
Material.PURPLE_WOOL,
Material.BLUE_WOOL,
Material.BROWN_WOOL,
Material.GREEN_WOOL,
Material.RED_WOOL,
Material.BLACK_WOOL
));
/**
* This {@link List} contains all stained glass colors ordered by their appearance ingame.
*/
public static final List<Material> STAINED_GLASS = Collections.unmodifiableList(Arrays.asList(
Material.WHITE_STAINED_GLASS,
Material.ORANGE_STAINED_GLASS,
Material.MAGENTA_STAINED_GLASS,
Material.LIGHT_BLUE_STAINED_GLASS,
Material.YELLOW_STAINED_GLASS,
Material.LIME_STAINED_GLASS,
Material.PINK_STAINED_GLASS,
Material.GRAY_STAINED_GLASS,
Material.LIGHT_GRAY_STAINED_GLASS,
Material.CYAN_STAINED_GLASS,
Material.PURPLE_STAINED_GLASS,
Material.BLUE_STAINED_GLASS,
Material.BROWN_STAINED_GLASS,
Material.GREEN_STAINED_GLASS,
Material.RED_STAINED_GLASS,
Material.BLACK_STAINED_GLASS
));
/**
* This {@link List} contains all stained glass pane colors ordered by their appearance ingame.
*/
public static final List<Material> STAINED_GLASS_PANE = Collections.unmodifiableList(Arrays.asList(
Material.WHITE_STAINED_GLASS_PANE,
Material.ORANGE_STAINED_GLASS_PANE,
Material.MAGENTA_STAINED_GLASS_PANE,
Material.LIGHT_BLUE_STAINED_GLASS_PANE,
Material.YELLOW_STAINED_GLASS_PANE,
Material.LIME_STAINED_GLASS_PANE,
Material.PINK_STAINED_GLASS_PANE,
Material.GRAY_STAINED_GLASS_PANE,
Material.LIGHT_GRAY_STAINED_GLASS_PANE,
Material.CYAN_STAINED_GLASS_PANE,
Material.PURPLE_STAINED_GLASS_PANE,
Material.BLUE_STAINED_GLASS_PANE,
Material.BROWN_STAINED_GLASS_PANE,
Material.GREEN_STAINED_GLASS_PANE,
Material.RED_STAINED_GLASS_PANE,
Material.BLACK_STAINED_GLASS_PANE
));
/**
* This {@link List} contains all terracotta colors ordered by their appearance ingame.
*/
public static final List<Material> TERRACOTTA = Collections.unmodifiableList(Arrays.asList(
Material.WHITE_TERRACOTTA,
Material.ORANGE_TERRACOTTA,
Material.MAGENTA_TERRACOTTA,
Material.LIGHT_BLUE_TERRACOTTA,
Material.YELLOW_TERRACOTTA,
Material.LIME_TERRACOTTA,
Material.PINK_TERRACOTTA,
Material.GRAY_TERRACOTTA,
Material.LIGHT_GRAY_TERRACOTTA,
Material.CYAN_TERRACOTTA,
Material.PURPLE_TERRACOTTA,
Material.BLUE_TERRACOTTA,
Material.BROWN_TERRACOTTA,
Material.GREEN_TERRACOTTA,
Material.RED_TERRACOTTA,
Material.BLACK_TERRACOTTA
));
/**
* This {@link List} contains all glazed terracotta colors ordered by their appearance ingame.
*/
public static final List<Material> GLAZED_TERRACOTTA = Collections.unmodifiableList(Arrays.asList(
Material.WHITE_GLAZED_TERRACOTTA,
Material.ORANGE_GLAZED_TERRACOTTA,
Material.MAGENTA_GLAZED_TERRACOTTA,
Material.LIGHT_BLUE_GLAZED_TERRACOTTA,
Material.YELLOW_GLAZED_TERRACOTTA,
Material.LIME_GLAZED_TERRACOTTA,
Material.PINK_GLAZED_TERRACOTTA,
Material.GRAY_GLAZED_TERRACOTTA,
Material.LIGHT_GRAY_GLAZED_TERRACOTTA,
Material.CYAN_GLAZED_TERRACOTTA,
Material.PURPLE_GLAZED_TERRACOTTA,
Material.BLUE_GLAZED_TERRACOTTA,
Material.BROWN_GLAZED_TERRACOTTA,
Material.GREEN_GLAZED_TERRACOTTA,
Material.RED_GLAZED_TERRACOTTA,
Material.BLACK_GLAZED_TERRACOTTA
));
/**
* This {@link List} contains all concrete colors ordered by their appearance ingame.
*/
public static final List<Material> CONCRETE = Collections.unmodifiableList(Arrays.asList(
Material.WHITE_CONCRETE,
Material.ORANGE_CONCRETE,
Material.MAGENTA_CONCRETE,
Material.LIGHT_BLUE_CONCRETE,
Material.YELLOW_CONCRETE,
Material.LIME_CONCRETE,
Material.PINK_CONCRETE,
Material.GRAY_CONCRETE,
Material.LIGHT_GRAY_CONCRETE,
Material.CYAN_CONCRETE,
Material.PURPLE_CONCRETE,
Material.BLUE_CONCRETE,
Material.BROWN_CONCRETE,
Material.GREEN_CONCRETE,
Material.RED_CONCRETE,
Material.BLACK_CONCRETE
));
}

View File

@ -109,12 +109,13 @@ public enum HeadTexture {
IRON_GOLEM("89091d79ea0f59ef7ef94d7bba6e5f17f2f7d4572c44f90f76c4819a714"),
PIGLIN_HEAD("2882af1294a74023e6919a31d1a027310f2e142afb4667d230d155e7f21dbb41");
public static final HeadTexture[] values = values();
public static final HeadTexture[] valuesCache = values();
private final String texture;
HeadTexture(@Nonnull String texture) {
Validate.notNull(texture, "Texture cannot be null");
Validate.isTrue(PatternUtils.HEXADECIMAL.matcher(texture).matches(), "Textures must be in hexadecimal.");
this.texture = texture;
}
@ -123,6 +124,7 @@ public enum HeadTexture {
*
* @return The associated texture hash
*/
@Nonnull
public String getTexture() {
return texture;
}
@ -132,6 +134,7 @@ public enum HeadTexture {
*
* @return A custom head {@link ItemStack}
*/
@Nonnull
public ItemStack getAsItemStack() {
return SlimefunUtils.getCustomHead(getTexture());
}

View File

@ -27,19 +27,30 @@ public final class NumberUtils {
return LocalDateTime.parse(date.substring(0, date.length() - 1));
}
/**
* This will return a representative color for the given percentage.
* Lower levels will result in a darker tone of red, higher levels will
* result in more brighter shades of green.
*
* @param percentage
* The amount of percentage as a float
*
* @return A representative {@link ChatColor}
*/
public static ChatColor getColorFromPercentage(float percentage) {
if (percentage < 16.0F)
if (percentage < 16.0F) {
return ChatColor.DARK_RED;
else if (percentage < 32.0F)
} else if (percentage < 32.0F) {
return ChatColor.RED;
else if (percentage < 48.0F)
} else if (percentage < 48.0F) {
return ChatColor.GOLD;
else if (percentage < 64.0F)
} else if (percentage < 64.0F) {
return ChatColor.YELLOW;
else if (percentage < 80.0F)
} else if (percentage < 80.0F) {
return ChatColor.DARK_GREEN;
else
} else {
return ChatColor.GREEN;
}
}
public static String getElapsedTime(@Nonnull LocalDateTime date) {

View File

@ -16,6 +16,7 @@ public final class PatternUtils {
private PatternUtils() {}
public static final Pattern COLON = Pattern.compile(":");
public static final Pattern SEMICOLON = Pattern.compile(";");
public static final Pattern HASH = Pattern.compile("#");
public static final Pattern COMMA = Pattern.compile(",");
@ -23,8 +24,12 @@ public final class PatternUtils {
public static final Pattern DASH = Pattern.compile("-");
public static final Pattern UNDERSCORE = Pattern.compile("_");
public static final Pattern ASCII = Pattern.compile("[A-Za-z \"_]+");
public static final Pattern ALPHANUMERIC = Pattern.compile("[A-Fa-f0-9]+");
public static final Pattern HEXADECIMAL = Pattern.compile("[A-Fa-f0-9]+");
public static final Pattern NUMERIC = Pattern.compile("[0-9]+");
public static final Pattern NUMBER_SEPARATOR = Pattern.compile("[,.]");
public static final Pattern MINECRAFT_MATERIAL = Pattern.compile("minecraft:[a-z_]+");
public static final Pattern MINECRAFT_TAG = Pattern.compile("#minecraft:[a-z_]+");
public static final Pattern SLIMEFUN_TAG = Pattern.compile("#slimefun:[a-z_]+");
}

View File

@ -215,7 +215,7 @@ public final class SlimefunUtils {
String base64 = texture;
if (PatternUtils.ALPHANUMERIC.matcher(texture).matches()) {
if (PatternUtils.HEXADECIMAL.matcher(texture).matches()) {
base64 = Base64.getEncoder().encodeToString(("{\"textures\":{\"SKIN\":{\"url\":\"http://textures.minecraft.net/texture/" + texture + "\"}}}").getBytes(StandardCharsets.UTF_8));
}
@ -250,20 +250,17 @@ public final class SlimefunUtils {
}
public static boolean isItemSimilar(@Nullable ItemStack item, @Nullable ItemStack sfitem, boolean checkLore, boolean checkAmount) {
if (item == null)
if (item == null) {
return sfitem == null;
if (sfitem == null)
} else if (sfitem == null) {
return false;
if (item.getType() != sfitem.getType())
} else if (item.getType() != sfitem.getType()) {
return false;
if (checkAmount && item.getAmount() < sfitem.getAmount())
} else if (checkAmount && item.getAmount() < sfitem.getAmount()) {
return false;
if (sfitem instanceof SlimefunItemStack && item instanceof SlimefunItemStack) {
} else if (sfitem instanceof SlimefunItemStack && item instanceof SlimefunItemStack) {
return ((SlimefunItemStack) item).getItemId().equals(((SlimefunItemStack) sfitem).getItemId());
}
if (item.hasItemMeta()) {
} else if (item.hasItemMeta()) {
ItemMeta itemMeta = item.getItemMeta();
if (sfitem instanceof SlimefunItemStack) {
@ -277,12 +274,12 @@ public final class SlimefunUtils {
return equalsItemMeta(itemMeta, meta, checkLore);
} else if (sfitem.hasItemMeta()) {
return equalsItemMeta(itemMeta, sfitem.getItemMeta(), checkLore);
} else {
return false;
}
} else {
return !sfitem.hasItemMeta();
}
return false;
}
private static boolean equalsItemMeta(@Nonnull ItemMeta itemMeta, @Nonnull ImmutableItemMeta meta, boolean checkLore) {

View File

@ -0,0 +1,327 @@
package io.github.thebusybiscuit.slimefun4.utils.tags;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Tag;
import org.bukkit.block.data.Waterlogged;
import io.github.thebusybiscuit.slimefun4.api.exceptions.TagMisconfigurationException;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.BlockPlacer;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.CropGrowthAccelerator;
import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.miner.IndustrialMiner;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ClimbingPick;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.ExplosiveShovel;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.PickaxeOfTheSeeker;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.PickaxeOfVeinMining;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.SmeltersPickaxe;
/**
* This enum contains various implementations of the {@link Tag} interface.
* Most of them serve some purpose within Slimefun's implementation, some are just pure
* extensions of the default Minecraft tags.
* The actual tag files are located in the {@literal /src/main/resources/tags} directory
* and follow Minecraft's tags.json format.
*
* @author TheBusyBiscuit
*
* @see TagParser
*
*/
public enum SlimefunTag implements Tag<Material> {
/**
* Minecraft ores.
*/
ORES,
/**
* All Shulker boxes, normal and colored.
*/
SHULKER_BOXES,
/**
* All command block variants
*/
COMMAND_BLOCKS,
/**
* Every mushroom type, red, brown and nether ones.
*/
MUSHROOMS,
/**
* Every glass variant, includes both blocks and panes.
* Also stained glass and stained glass panes.
*/
GLASS,
/**
* All variants of glass, normal and stained.
*/
GLASS_BLOCKS,
/**
* All variants of glass panes, normal and stained.
*/
GLASS_PANES,
/**
* All variants of torches, normal, soulfire and redstone.
*/
TORCHES,
/**
* All terracotta variants, does not include glazed terracotta.
*/
TERRACOTTA,
/**
* All ice variants, normal, packed, blue and whatever else there is.
*/
ICE_VARIANTS,
/**
* All stone variants, normal, andesite, diorite, granite and whatever else may come.
*/
STONE_VARIANTS,
/**
* All variants of concrete powder.
* Can you believe there is no tag for this already?
*/
CONCRETE_POWDERS,
/**
* Materials which are sensitive to break.
* Things like Saplings or Pressure plates which break as well when you break
* the block beneath them.
*/
SENSITIVE_MATERIALS,
/**
* These Materials are sensitive to fluids, they cannot be {@link Waterlogged}
* and would break in contact with water.
*/
FLUID_SENSITIVE_MATERIALS,
/**
* These materials are just unbreakable, like bedrock for example.
*/
UNBREAKABLE_MATERIALS,
/**
* Materials which cannot be reliably placed using a {@link BlockPlacer}.
*/
BLOCK_PLACER_IGNORED_MATERIALS,
/**
* All materials which the {@link ExplosiveShovel} can break.
*/
EXPLOSIVE_SHOVEL_BLOCKS,
/**
* All materials (ores) which the {@link PickaxeOfVeinMining} recognizes.
*/
PICKAXE_OF_VEIN_MINING_BLOCKS,
/**
* All materials (ores) which the {@link PickaxeOfTheSeeker} recognizes.
*/
PICKAXE_OF_THE_SEEKER_BLOCKS,
/**
* All materials which the {@link SmeltersPickaxe} will try and smelt.
*/
SMELTERS_PICKAXE_BLOCKS,
/**
* All materials (ores) which the {@link IndustrialMiner} will try to mine.
*/
INDUSTRIAL_MINER_ORES,
/**
* All materials (crops) which the {@link CropGrowthAccelerator} will recognize.
*/
CROP_GROWTH_ACCELERATOR_BLOCKS,
/**
* All <strong>strong</strong> materials which the {@link ClimbingPick} is able to climb.
*/
CLIMBING_PICK_STRONG_SURFACES,
/**
* All <strong>weak</strong> materials which the {@link ClimbingPick} is able to climb.
*/
CLIMBING_PICK_WEAK_SURFACES,
/**
* This {@link SlimefunTag} holds all surfaces for the {@link ClimbingPick}.
* This is an aggregation of {@code CLIMBING_PICK_STRONG_SURFACES} and {@code CLIMBING_PICK_WEAK_SURFACES}
*/
CLIMBING_PICK_SURFACES,
/**
* All materials (ores) which trigger the Talisman of the Caveman.
*/
CAVEMAN_TALISMAN_TRIGGERS;
private static final Map<String, SlimefunTag> nameLookup = new HashMap<>();
public static final SlimefunTag[] valuesCache = values();
static {
for (SlimefunTag tag : valuesCache) {
nameLookup.put(tag.name(), tag);
}
}
private final NamespacedKey key;
private final Set<Material> includedMaterials = EnumSet.noneOf(Material.class);
private final Set<Tag<Material>> additionalTags = new HashSet<>();
/**
* This constructs a new {@link SlimefunTag}.
* The {@link NamespacedKey} will be automatically inferred using
* {@link SlimefunPlugin} and {@link #name()}.
*/
SlimefunTag() {
key = new NamespacedKey(SlimefunPlugin.instance(), name().toLowerCase(Locale.ROOT));
}
/**
* This method reloads this {@link SlimefunTag} from our resources directory.
*
* @throws TagMisconfigurationException
* This is thrown whenever a {@link SlimefunTag} could not be parsed properly
*/
public void reload() throws TagMisconfigurationException {
new TagParser(this).parse(this, (materials, tags) -> {
this.includedMaterials.clear();
this.includedMaterials.addAll(materials);
this.additionalTags.clear();
this.additionalTags.addAll(tags);
});
}
/**
* This method reloads every single {@link SlimefunTag} from the resources directory.
* It is equivalent to running {@link #reload()} on every single {@link SlimefunTag} manually.
*
* Do keep in mind though that any misconfigured {@link SlimefunTag} will abort the entire
* method and throw a {@link TagMisconfigurationException}. So one faulty {@link SlimefunTag}
* will stop the reloading process.
*
* @throws TagMisconfigurationException
* This is thrown if one of the {@link SlimefunTag SlimefunTags} could not be parsed correctly
*/
public static void reloadAll() throws TagMisconfigurationException {
for (SlimefunTag tag : valuesCache) {
tag.reload();
}
}
@Nonnull
@Override
public NamespacedKey getKey() {
return key;
}
@Override
public boolean isTagged(@Nonnull Material item) {
if (includedMaterials.contains(item)) {
return true;
} else {
// Check if any of our additional Tags contain this Materials
for (Tag<Material> tag : additionalTags) {
if (tag.isTagged(item)) {
return true;
}
}
// Now we can be sure it isn't tagged in any way
return false;
}
}
@Nonnull
@Override
public Set<Material> getValues() {
if (additionalTags.isEmpty()) {
return Collections.unmodifiableSet(includedMaterials);
} else {
Set<Material> materials = EnumSet.noneOf(Material.class);
materials.addAll(includedMaterials);
for (Tag<Material> tag : additionalTags) {
materials.addAll(tag.getValues());
}
return materials;
}
}
/**
* This returns a {@link Set} of {@link Tag Tags} which are children of this {@link SlimefunTag},
* these can be other {@link SlimefunTag SlimefunTags} or regular {@link Tag Tags}.
*
* <strong>The returned {@link Set} is immutable</strong>
*
* @return An immutable {@link Set} of all sub tags.
*/
@Nonnull
public Set<Tag<Material>> getSubTags() {
return Collections.unmodifiableSet(additionalTags);
}
/**
* This method returns an Array representation for this {@link SlimefunTag}.
*
* @return A {@link Material} array for this {@link Tag}
*/
@Nonnull
public Material[] toArray() {
return getValues().toArray(new Material[0]);
}
/**
* This returns a {@link Stream} of {@link Material Materials} for this {@link SlimefunTag}.
*
* @return A {@link Stream} of {@link Material Materials}
*/
@Nonnull
public Stream<Material> stream() {
return getValues().stream();
}
/**
* Get a value from the cache map rather than calling {@link Enum#valueOf(Class, String)}.
* This is 25-40% quicker than the standard {@link Enum#valueOf(Class, String)} depending on
* your Java version. It also means that you can avoid an IllegalArgumentException which let's
* face it is always good.
*
* @param value
* The value which you would like to look up.
*
* @return The {@link SlimefunTag} or null if it does not exist.
*/
@Nullable
public static SlimefunTag getTag(@Nonnull String value) {
Validate.notNull(value, "A tag cannot be null!");
return nameLookup.get(value);
}
}

View File

@ -0,0 +1,196 @@
package io.github.thebusybiscuit.slimefun4.utils.tags;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Keyed;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Tag;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import io.github.thebusybiscuit.slimefun4.api.exceptions.TagMisconfigurationException;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
/**
* The {@link TagParser} is responsible for parsing a JSON input into a {@link SlimefunTag}.
*
* @author TheBusyBiscuit
*
* @see SlimefunTag
*
*/
public class TagParser implements Keyed {
private final NamespacedKey key;
/**
* This constructs a new {@link TagParser}.
*
* @param key
* The {@link NamespacedKey} of the resulting {@link SlimefunTag}
*/
public TagParser(@Nonnull NamespacedKey key) {
this.key = key;
}
/**
* This constructs a new {@link TagParser} for the given {@link SlimefunTag}
*
* @param tag
* The {@link SlimefunTag} to parse inputs for
*/
TagParser(@Nonnull SlimefunTag tag) {
this(tag.getKey());
}
void parse(@Nonnull SlimefunTag tag, @Nonnull BiConsumer<Set<Material>, Set<Tag<Material>>> callback) throws TagMisconfigurationException {
String path = "/tags/" + tag.getKey().getKey() + ".json";
try (BufferedReader reader = new BufferedReader(new InputStreamReader(SlimefunPlugin.class.getResourceAsStream(path), StandardCharsets.UTF_8))) {
parse(reader.lines().collect(Collectors.joining("")), callback);
} catch (IOException x) {
throw new TagMisconfigurationException(key, x);
}
}
/**
* This will parse the given JSON {@link String} and run the provided callback with {@link Set Sets} of
* matched {@link Material Materials} and {@link Tag Tags}.
*
* @param json
* The JSON {@link String} to parse
* @param callback
* A callback to run after successfully parsing the input
*
* @throws TagMisconfigurationException
* This is thrown whenever the given input is malformed or no adequate
* {@link Material} or {@link Tag} could be found
*/
public void parse(@Nonnull String json, @Nonnull BiConsumer<Set<Material>, Set<Tag<Material>>> callback) throws TagMisconfigurationException {
Validate.notNull(json, "Cannot parse a null String");
try {
Set<Material> materials = EnumSet.noneOf(Material.class);
Set<Tag<Material>> tags = new HashSet<>();
JsonParser parser = new JsonParser();
JsonObject root = parser.parse(json).getAsJsonObject();
JsonElement child = root.get("values");
if (child instanceof JsonArray) {
JsonArray values = child.getAsJsonArray();
for (JsonElement element : values) {
if (element instanceof JsonPrimitive && ((JsonPrimitive) element).isString()) {
// Strings will be parsed directly
parsePrimitiveValue(element.getAsString(), materials, tags, true);
} else if (element instanceof JsonObject) {
// JSONObjects can have a "required" property which can make
// it optional to resolve the underlying value
parseComplexValue(element.getAsJsonObject(), materials, tags);
} else {
throw new TagMisconfigurationException(key, "Unexpected value format: " + element.getClass().getSimpleName() + " - " + element.toString());
}
}
// Run the callback with the filled-in materials and tags
callback.accept(materials, tags);
} else {
// The JSON seems to be empty yet valid
throw new TagMisconfigurationException(key, "No values array specified");
}
} catch (IllegalStateException | JsonParseException x) {
throw new TagMisconfigurationException(key, x);
}
}
@ParametersAreNonnullByDefault
private void parsePrimitiveValue(String value, Set<Material> materials, Set<Tag<Material>> tags, boolean throwException) throws TagMisconfigurationException {
if (PatternUtils.MINECRAFT_MATERIAL.matcher(value).matches()) {
// Match the NamespacedKey against Materials
Material material = Material.matchMaterial(value);
if (material != null) {
// If the Material could be matched, simply add it to our Set
materials.add(material);
} else if (throwException) {
throw new TagMisconfigurationException(key, "Minecraft Material '" + value + "' seems to not exist!");
}
} else if (PatternUtils.MINECRAFT_TAG.matcher(value).matches()) {
// Get the actual Key portion and match it to item and block tags.
String keyValue = PatternUtils.COLON.split(value)[1];
NamespacedKey namespacedKey = NamespacedKey.minecraft(keyValue);
Tag<Material> itemsTag = Bukkit.getTag(Tag.REGISTRY_ITEMS, namespacedKey, Material.class);
Tag<Material> blocksTag = Bukkit.getTag(Tag.REGISTRY_BLOCKS, namespacedKey, Material.class);
if (itemsTag != null) {
// We will prioritize the item tag
tags.add(itemsTag);
} else if (blocksTag != null) {
// If no item tag exists, fall back to the block tag
tags.add(blocksTag);
} else if (throwException) {
// If both fail, then the tag does not exist.
throw new TagMisconfigurationException(key, "There is no '" + value + "' tag in Minecraft.");
}
} else if (PatternUtils.SLIMEFUN_TAG.matcher(value).matches()) {
// Get a SlimefunTag enum value for the given key
String keyValue = PatternUtils.COLON.split(value)[1].toUpperCase(Locale.ROOT);
SlimefunTag tag = SlimefunTag.getTag(keyValue);
if (tag != null) {
tags.add(tag);
} else if (throwException) {
throw new TagMisconfigurationException(key, "There is no '" + value + "' tag in Slimefun");
}
} else if (throwException) {
// If no RegEx pattern matched, it's malformed.
throw new TagMisconfigurationException(key, "Could not recognize value '" + value + "'");
}
}
@ParametersAreNonnullByDefault
private void parseComplexValue(JsonObject entry, Set<Material> materials, Set<Tag<Material>> tags) throws TagMisconfigurationException {
JsonElement id = entry.get("id");
JsonElement required = entry.get("required");
// Check if the entry contains elements of the correct type
if (id instanceof JsonPrimitive && ((JsonPrimitive) id).isString() && required instanceof JsonPrimitive && ((JsonPrimitive) required).isBoolean()) {
boolean isRequired = required.getAsBoolean();
// If the Tag is required, an exception may be thrown.
// Otherwise it will just ignore the value
parsePrimitiveValue(id.getAsString(), materials, tags, isRequired);
} else {
throw new TagMisconfigurationException(key, "Found a JSON Object value without an id!");
}
}
@Nonnull
@Override
public NamespacedKey getKey() {
return key;
}
}

View File

@ -0,0 +1,4 @@
/**
* This package holds utilities related to the {@link io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag} enum.
*/
package io.github.thebusybiscuit.slimefun4.utils.tags;

View File

@ -14,7 +14,12 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
// This interface should be reconsidered and moved at some point too
/**
*
* @deprecated This interface is not designed to be used by addons.
*
*/
@Deprecated
public interface InventoryBlock {
/**
@ -47,10 +52,11 @@ public interface InventoryBlock {
@Override
public int[] getSlotsAccessedByItemTransport(ItemTransportFlow flow) {
if (flow == ItemTransportFlow.INSERT)
if (flow == ItemTransportFlow.INSERT) {
return getInputSlots();
else
} else {
return getOutputSlots();
}
}
@Override

View File

@ -274,7 +274,7 @@ public class SlimefunItemStack extends CustomItem {
if (texture.startsWith("ey")) {
return texture;
} else if (PatternUtils.ALPHANUMERIC.matcher(texture).matches()) {
} else if (PatternUtils.HEXADECIMAL.matcher(texture).matches()) {
return Base64.getEncoder().encodeToString(("{\"textures\":{\"SKIN\":{\"url\":\"http://textures.minecraft.net/texture/" + texture + "\"}}}").getBytes(StandardCharsets.UTF_8));
} else {
throw new IllegalArgumentException("The provided texture for Item \"" + id + "\" does not seem to be a valid texture String!");

View File

@ -33,8 +33,9 @@ public class BlockMenu extends DirtyChestMenu {
this.location = l;
for (int i = 0; i < 54; i++) {
if (cfg.contains(String.valueOf(i)))
if (cfg.contains(String.valueOf(i))) {
addItem(i, cfg.getItem(String.valueOf(i)));
}
}
preset.clone(this);
@ -101,6 +102,7 @@ public class BlockMenu extends DirtyChestMenu {
public void dropItems(Location l, int... slots) {
for (int slot : slots) {
ItemStack item = getItemInSlot(slot);
if (item != null) {
l.getWorld().dropItemNaturally(l, item);
replaceExistingItem(slot, null);

View File

@ -82,10 +82,11 @@ public class DirtyChestMenu extends ChestMenu {
@Override
public ChestMenu addMenuOpeningHandler(MenuOpeningHandler handler) {
if (handler instanceof SaveHandler) {
return super.addMenuOpeningHandler(new SaveHandler(this, ((SaveHandler) handler).getOpeningHandler()));
if (handler instanceof MenuSavingHandler) {
MenuOpeningHandler openingHandler = ((MenuSavingHandler) handler).getOpeningHandler();
return super.addMenuOpeningHandler(new MenuSavingHandler(this, openingHandler));
} else {
return super.addMenuOpeningHandler(new SaveHandler(this, handler));
return super.addMenuOpeningHandler(new MenuSavingHandler(this, handler));
}
}
@ -170,26 +171,4 @@ public class DirtyChestMenu extends ChestMenu {
markDirty();
}
public static class SaveHandler implements MenuOpeningHandler {
private final DirtyChestMenu menu;
private final MenuOpeningHandler handler;
public SaveHandler(DirtyChestMenu menu, MenuOpeningHandler handler) {
this.menu = menu;
this.handler = handler;
}
@Override
public void onOpen(Player p) {
handler.onOpen(p);
menu.markDirty();
}
public MenuOpeningHandler getOpeningHandler() {
return handler;
}
}
}

View File

@ -0,0 +1,30 @@
package me.mrCookieSlime.Slimefun.api.inventory;
import javax.annotation.ParametersAreNonnullByDefault;
import org.bukkit.entity.Player;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu.MenuOpeningHandler;
public class MenuSavingHandler implements MenuOpeningHandler {
private final DirtyChestMenu menu;
private final MenuOpeningHandler handler;
@ParametersAreNonnullByDefault
public MenuSavingHandler(DirtyChestMenu menu, MenuOpeningHandler handler) {
this.menu = menu;
this.handler = handler;
}
@Override
public void onOpen(Player p) {
handler.onOpen(p);
menu.markDirty();
}
public MenuOpeningHandler getOpeningHandler() {
return handler;
}
}

View File

@ -33,8 +33,10 @@ public class UniversalBlockMenu extends DirtyChestMenu {
}
public void save() {
if (!isDirty())
if (!isDirty()) {
return;
}
// To force CS-CoreLib to build the Inventory
this.getContents();

View File

@ -23,3 +23,4 @@ slimefun:
easter: Великден (април)
birthday: Рожденият Ден на TheBusyBiscuit (26ти Октомври)
halloween: Хелоуин (31и Октомври)
androids: Програмируеми Андроиди

View File

@ -2,25 +2,25 @@
slimefun:
weapons: Fegyverek
tools: Eszközök
items: Hasznos Tárgyak
items: Hasznos tárgyak
food: Étel
basic_machines: Alapvető Gépek
electricity: Energia és Elektromosság
gps: GPS-alapú Gépek
basic_machines: Alapvető gépek
electricity: Energia és elektromosság
gps: GPS-alapú gépek
armor: Páncél
magical_items: Varázslatos Tárgyak
magical_gadgets: Varázslatos Kütyük
misc: Egyéb Tárgyak
technical_gadgets: Technikai Kütyük
magical_items: Varázslatos tárgyak
magical_gadgets: Varázslatos kütyük
misc: Egyéb tárgyak
technical_gadgets: Technikai kütyük
resources: Erőforrások
cargo: Szállítmány Kezelés
tech_misc: Műszaki Alkatrészek
magical_armor: Varázslatos Páncél
talismans: Talizmánok (I. Szint)
ender_talismans: Ender Talizmánok (II. Szint)
cargo: Szállítmánykezelés
tech_misc: Műszaki alkatrészek
magical_armor: Varázslatos páncél
talismans: Talizmánok (I. szint)
ender_talismans: Ender talizmánok (II. szint)
christmas: Karácsony (December)
valentines_day: Valentin Nap (Február 14.)
valentines_day: Valentin nap (Február 14.)
easter: Húsvét (Április)
birthday: TheBusyBiscuit születésnapja (Október 26.)
halloween: Halloween (Október 31.)
androids: Programozható Androidok
androids: Programozható androidok

View File

@ -23,3 +23,4 @@ slimefun:
easter: Pasen (April)
birthday: TheBusyBiscuit's Verjaardag (26 October)
halloween: Halloween (31 October)
androids: Programmeerbare Robots

View File

@ -21,6 +21,10 @@ commands:
backpack-does-not-exist: "&4Der angegebene Rucksack konnte nicht gefunden werden!"
restored-backpack-given: "&aDein Rucksack wurde erfolgreich wiederhergestellt
und deinem Inventar hinzugefügt!"
charge:
description: Lädt das Item in deiner Hand auf
charge-success: Dein Item wurde erfolgreich aufgeladen!
not-rechargeable: Dieses Item kann nicht aufgeladen werden!
guide:
search:
message: "&bWonach möchtest du suchen?"
@ -130,6 +134,7 @@ messages:
whirlwind: "&a&oDein Talisman hat soeben ein Projektil reflektiert"
wizard: "&a&oDein Talisman hat dein Glück-Level erhöht aber möglicherweise das
Level einer anderen Verzauberung vermindert"
caveman: "&a&oDein Talisman hat dir einen Abbau-Boost verschafft"
soulbound-rune:
fail: "&cDu kannst nicht mehrere Items auf einmal an deine Seele binden"
success: "&aDu hast dieses Item erfolgreich an deine Seele gebunden! Solltest
@ -329,7 +334,6 @@ languages:
zh-CN: Chinesisch (China)
el: Griechisch
he: Hebräisch
pt: Portugiesisch (Portugal)
pt-BR: Portugiesisch (Brasilien)
ar: Arabisch
af: Afrikaans
@ -342,6 +346,7 @@ languages:
fa: Persisch
th: Thailändisch
ro: Rumänisch
pt: Portugiesisch (Portugal)
bg: Bulgarisch
ko: Koreanisch
tr: Türkisch
@ -354,5 +359,7 @@ brewing_stand:
not-working: "&4Items von Slimefun können nicht zum Brauen verwendet werden!"
villagers:
no-trading: "&4Items von Slimefun können nicht zum Handeln verwendet werden!"
cartography_table:
not-working: "&4Slimefun Items können nicht in einem Kartentisch verwendet werden!"
miner:
no-ores: "&eIch konnte leider keine Erze in der Nähe finden!"

View File

@ -21,6 +21,10 @@ commands:
backpack-does-not-exist: "&4Le sac à dos spécifié n'existe pas!"
restored-backpack-given: "&aVotre sac à dos a été restauré et a été ajouté à votre
inventaire!"
charge:
description: Charge l'objet que vous avez en main
charge-success: L'objet a été chargé !
not-rechargeable: Cet objet ne peut pas être chargé !
guide:
search:
message: "&bQue souhaitez-vous rechercher?"
@ -133,6 +137,7 @@ messages:
whirlwind: "&a&oVotre talisman a renvoyé le projectile"
wizard: "&a&oVotre talisman vous a donné un meilleur niveau de Fortune mais a
peut-être diminué plusieurs autres enchantements"
caveman: "&a&oVotre Talisman vous a donné Célérité"
soulbound-rune:
fail: "&cVous pouvez lier un seul objet à la fois à votre âme"
success: "&aVous avez réussi à lier cet objet à votre âme! Vous le garderez quand
@ -335,7 +340,6 @@ languages:
zh-CN: Chinois (Chine)
el: Grec
he: Hébreu
pt-BR: Portugais (Brésil)
ar: Arabe
af: Afrikaans
da: Danois
@ -348,6 +352,7 @@ languages:
th: Thaï
ro: Roumain
pt: Portugais (Portugal)
pt-BR: Portugais (Brésil)
bg: Bulgare
ko: Coréen
tr: Turc
@ -361,5 +366,8 @@ brewing_stand:
villagers:
no-trading: "&4Vous ne pouvez pas échanger des objets Slimefun avec les villageois
!"
cartography_table:
not-working: "&4Vous ne pouvez pas utiliser d'objets Slimefun dans une table de
cartographie !"
miner:
no-ores: "&eDésolé, je n'ai pas pu trouver de minerai à proximité !"

View File

@ -1,28 +1,32 @@
---
commands:
help: Megjeleníti ezt a súgóképernyőt
cheat: Lehetővé teszi a Tárgyak csalását
give: Adj valakinek Slimefun Tárgyakat
guide: Adj magadnak egy Slimefun Útmutatót
timings: Lag-Információ a Szerverről
teleporter: Nézd meg a többi Játékos Útpontjait
versions: Az összes telepített Kiegészítőt listázza
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
open_guide: A könyv használata nélkül megnyitja a Slimefun útmutatóját
stats: Néhány statisztikát mutat a Játékosról
stats: Néhány statisztikát mutat egy játékosról
research:
description: A játékosok kutatásainak Feloldása/Visszaállítása
reset: "&cVisszaállítottad %player% Ismereteit"
description: A játékosok kutatásainak feloldása/visszaállítása
reset: "&cVisszaállítottad %player% ismereteit"
reset-target: "&cAz ismereteidet visszaállították"
backpack:
description: Lekéri egy meglévő hátizsák másolatát
invalid-id: "&4Az azonosító nem lehet negatív szám!"
player-never-joined: "&4Nincs ilyen nevű játékos!"
backpack-does-not-exist: "&4A megadott hátizsák nem létezik!"
restored-backpack-given: "&aA hátizsákod visszaállítva és hozzáadva a leltáradhoz!"
restored-backpack-given: "&aA hátizsákod visszaállítva és hozzáadva az eszköztáradhoz!"
charge:
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!
guide:
search:
message: "&bMit szeretnél keresni?"
message: "&bMire szeretnél keresni?"
name: "&7Keresés..."
tooltip: "&bKlikk egy tárgy kereséséhez"
inventory: 'Keresés erre: %item%'
@ -30,33 +34,46 @@ guide:
- "&bMit szeretnél keresni?"
- "&7Gépeld be a keresett kifejezést a chatbe"
cheat:
no-multiblocks: "&4A Multiblokkban nem tudsz csalni, meg kell építened!"
no-multiblocks: "&4Multiblockot nem tudsz lekérni, meg kell építened!"
languages:
updated: "&aA nyelvet sikeresen átállítottad erre: &b%lang%"
translations:
name: "&aHiányzik valami?"
lore: Kattints a saját fordítás hozzáadásához
lore: Kattints saját fordítás hozzáadásához
select: Kattints a nyelv kiválasztásához
select-default: Kattints az alapértelmezett nyelv kiválasztásához
selected-language: 'Jelenleg kiválasztva:'
change: Kattints a nyelv kiválasztásához
description:
- "&7Már lehetőséged van kiválasztani,"
- "&7hogy a Slimefun milyen nyelven"
- "&7jelenjen meg számodra. A tárgyakat"
- "&7jelenleg nem lehet lefordítani."
title:
main: Slimefun Útmutató
settings: Beállítások és Információk
languages: Válaszd ki a kívánt nyelvet
credits: Slimefun4 Közreműködők
credits: Slimefun4 közreműködők
wiki: Slimefun4 Wiki
addons: A Slimefun4 kiegészítői
bugs: Hibajelentések
source: Forráskód
versions: Telepített verziók
credits:
commit: Commit
commits: Commits
commit: commit
commits: commits
roles:
developer: "&6Fejlesztő"
wiki: "&3Wiki Szerkesztő"
resourcepack: "&cForráscsomag Művész"
wiki: "&3Wiki szerkesztő"
resourcepack: "&cForráscsomag művész"
translator: "&9Fordító"
profile-link: Kattints ide, hogy meglátogasd a profilját a GitHub-on
open: Kattints a közreműködők megtekintéséhez
description:
- "&7A Slimefun egy nyílt forráskódú projekt,"
- "&7amit egy hatalmas közösség tart fenn."
- "&7Több mint &e%contributors% &7közreműködő"
- "&7dolgozott rajta az évek során."
pages:
previous: Előző oldal
next: Következő oldal
@ -65,56 +82,57 @@ guide:
versions-notice: Ezek nagyon fontosak a hibák jelentésekor!
wiki: Tekintsd meg ezt a tárgyat a hivatalos Slimefun Wikin
recipes:
machine: Ebben a Gépben készített receptek
miner: Erőforrások, amelyeket ezzel a Bányásszal szerezhetsz be
machine: Ebben a gépben készíthető receptek
miner: Erőforrások, amelyeket ezzel a bányásszal szerezhetsz be
generator: Rendelkezésre álló üzemanyagtípusok
gold-pan: Megszerezhető források
gold-pan: Megszerezhető erőforrások
climbing-pick: Megmászható felületek
back:
title: Vissza
guide: Menj vissza a Slimefun Útmutatóba
settings: Menj vissza a Beállítások Panelre
guide: Visszalépés a Slimefun Útmutatóba
settings: Visszalépés a Beállítások panelre
locked: LEZÁRVA
locked-category:
- Ennek a kategóriának a feloldásához
- fel kell oldanod az összes tárgyat a
- következő kategóriákból
- fel kell oldanod az összes tárgyat
- a következő kategóriákból
work-in-progress: Ez a funkció még nem készült el teljesen!
messages:
not-researched: "&4Nincs elég ismereted ennek a megértéséhez"
not-researched: "&4Nincs elég ismereted, hogy megértsd ezt"
not-enough-xp: "&4Nincs elég XP-d ennek a feloldásához"
unlocked: '&7"%research%" &bfeloldva'
only-players: "&4Ez a parancs csak a Játékosok számára szól"
unknown-player: "&4Ismeretlen Játékos: &c%player%"
no-permission: "&4Nem rendelkezel a szükséges engedélyekkel ehhez"
only-players: "&4Ezt a parancsot csak játékosok használhatják"
unknown-player: "&4Ismeretlen játékos: &c%player%"
no-permission: "&4Ehhez nincs jogod"
usage: "&4Használat: &c%usage%"
not-online: "&4%player% &cnincs online!"
not-valid-item: "&4%item% &cnem megfelelő Tárgy!"
not-valid-amount: "&4%amount% &cnem megfelelő mennyiség : 0-nál nagyobbnak kell
lennie!"
given-item: '&bKaptál &a%amount% &7"%item%&7"&b-t'
not-online: "&4%player% &cjelenleg nem elérhető!"
not-valid-item: "&4%item% &cnem megfelelő tárgy!"
not-valid-amount: "&4%amount% &cnem megfelelő mennyiség: 0-nál nagyobbnak kell lennie!"
given-item: '&bKaptál &a%amount% darab &7"%item%&7"&b-t'
give-item: '&bAdtál %player%-nek/nak &a%amount% &7"%item%&7"&b-t'
not-valid-research: "&4%research% &cnem érvényes Kutatás!"
give-research: '&bAdtál %player%-nek/nak &7"%research%&7" &bKutatást'
give-research: '&bMegadtad %player% játékosnak a(z) &7"%research%&7" &bkutatást'
hungry: "&cTúl éhes vagy ehhez!"
mode-change: "&b%device% mód állítva erre: &9%mode%"
disabled-in-world: "&4&lEz a Tárgy tiltva van ebben a világban"
disabled-item: "&4&lEz a Tárgy le van tiltva! Egyáltalán hogyan szerezted?"
no-tome-yourself: "&cNem tudod használni a &4Tome of Knowledge &c-t magadon..."
multimeter: "&bTárolt Energia: &3%stored% &b/ &3%capacity%"
disabled-in-world: "&4&lEz a tárgy tiltva van ebben a világban"
disabled-item: "&4&lEz a tárgy le van tiltva! Egyáltalán hogyan szerezted?"
no-tome-yourself: "&cNem használhatod a &4Tome of Knowledge&c-t magadon..."
multimeter: "&bTárolt energia: &3%stored% &b/ &3%capacity%"
talisman:
anvil: "&a&oA Talizmánod megmentette az eszközöd a töréstől"
miner: "&a&oA Talizmánod megduplázta a dobott tárgyakat"
hunter: "&a&oA Talizmánod megduplázta a dobott tárgyakat"
lava: "&a&oA Talizmánod megmentett a halálos égéstől"
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"
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 élet Regenerációt"
whirlwind: "&a&oA Talizmánod visszavert egy Távolsági lövést"
wizard: "&a&oA Talizmánod erősítette a Szerencse Szinjét, de néhány egyéb Fejlesztés
Szint kicsit gyengül"
anvil: "&a&oA talizmánod megmentette az eszközöd az eltöréstől"
miner: "&a&oA talizmánod megduplázta a dobott tárgyakat"
hunter: "&a&oA talizmánod megduplázta a dobott tárgyakat"
lava: "&a&oA talizmánod megmentett a halálos égéstől"
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"
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"
caveman: "&a&oA talizmánod adott Sietség effektet"
soulbound-rune:
fail: "&cEgyszerre csak egy tárgyat köthetsz a lelkedhez."
success: "&aSikeresen hozzákötötted ezt a tárgyat a lelkedhez! Megmarad, amikor
@ -129,65 +147,73 @@ messages:
vagy viselj Hazmat Suit-ot!"
opening-guide: "&bÚtmutató megnyitása, ez eltarthat pár másodpercig..."
opening-backpack: "&bHátizsák megnyitása, ez eltarthat pár másodpercig..."
no-iron-golem-heal: "&cEz nem egy Vasrúd. Ezt nem használhatod a Vasgólem gyógyítására!"
no-iron-golem-heal: "&cEz nem egy vasrúd. Ezt nem használhatod a vasgólem gyógyítására!"
link-prompt: "&eKattints ide:"
diet-cookie: "&eNagyon könnyednek érzed magad..."
fortune-cookie:
- "&7Segítség, csapdába estem egy Szerencsesüti Gyárban!"
- "&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
játékban vagy"
- "&7Ez a süti néhány másodperc alatt jó ízű lesz"
- '&7Az utolsó szó, amelyet hallani fogsz, "KIÍRTANI!!!"'
- "&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."
- "&7Soha ne áss egyenesen!"
- "&7Ez csak egy friss sebesülés!"
- "&7Ez csak egy kis karcolás!"
- "&7Mindig nézd az élet jó oldalát!"
- "&7Ez valójában Keksz volt, és nem Süti"
- "&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 a Piglinekkel."
piglin-barter: "&4Slimefun tárgyakat nem cserélhetsz el piglinekkel."
enchantment-rune:
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."
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."
tape-measure:
no-anchor: "&cBe kell állítanod egy rögzítést, mielőtt megkezdenéd a mérést!"
wrong-world: "&cA rögzítés úgy tűnik egy másik világban van!"
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!"
distance: "&7A mérés megtörtént. &eA távolság: %distance%"
anchor-set: "&aA rögzítés sikeresen beállítva:&e %anchor%"
anchor-set: "&aA kezdőpont sikeresen beállítva:&e %anchor%"
multi-tool:
mode-change: "&b%device% mód átállítva: &9%mode%"
not-shears: "&cA Multi Tool nem használható óllóként!"
climbing-pick:
dual-wielding: "&4Mindkét kezedben Climbing Pick-et kell tartanod, hogy használhasd
őket!"
wrong-material: "&cEzt a felületet nem mászhatod meg. Nyisd meg a Slimefun Útmutatót
további információért!"
mode-change: "&b%device% mód állítva erre: &9%mode%"
machines:
pattern-not-found: "&eSajnálom, nem ismerem fel ezt a Receptet. Kérlek, helyezd
a Tárgyakat a megfelelő mintában az Adagolóba."
unknown-material: "&eSajnálom, Nem tudtam felismerni a Tárgyat az adagolóban. Kérlek
pattern-not-found: "&eSajnálom, nem ismerem fel ezt a receptet. Kérlek, helyezd
a tárgyakat a megfelelő mintában az adagolóba."
unknown-material: "&eSajnálom, nem tudtam felismerni a tárgyat az adagolóban. Kérlek
tegyél bele valamit, amit ismerek."
wrong-item: "&eSajnálom, nem ismerem fel azt a Tárgyat, amire kattintottál velem.
Ellenőrizd a Recepteket, és nézd meg, mely Tárgyakat használhatod."
full-inventory: "&eSajnálom, tele a tárolóm!"
in-use: "&cEnnek a Blokknak a tárolóját éppen megnyitotta egy másik Játékos."
ignition-chamber-no-flint: "&cA Gyújtókamrából hiányzik a Kovakő és Acél."
wrong-item: "&eSajnálom, nem ismerem fel azt a tárgyat, amire velem kattintottál.
Ellenőrizd a recepteket, és nézd meg, mely tárgyakat használhatod."
full-inventory: "&eSajnálom, tele az eszköztáram!"
in-use: "&cEnnek a blokknak az eszköztárát éppen megnyitotta egy másik játékos."
ignition-chamber-no-flint: "&cAz Ignition Chamber-ből hiányzik a kovakő és acél."
ANCIENT_ALTAR:
not-enough-pedestals: "&4Az Oltár körül nincs elég Talapzat, ami szükséges a működéséhez
not-enough-pedestals: "&4Az Altar körül nincs elég Pedestal, ami szükséges a működéséhez
&c(%pedestals% / 8)"
unknown-catalyst: "&4Ismeretlen Katalizátor! &cEhelyett használd a helyes Receptet!"
unknown-recipe: "&4Ismeretlen Recept! &cEhelyett használd a helyes Receptet!"
unknown-catalyst: "&4Ismeretlen katalizátor! &cEhelyett használd a helyes receptet!"
unknown-recipe: "&4Ismeretlen recept! &cEhelyett használd a helyes receptet!"
ANCIENT_PEDESTAL:
obstructed: "&4A Talapzat el van torlaszolva! &cTávolíts el mindent, ami a talapzat
obstructed: "&4A Pedestal el van torlaszolva! &cTávolíts el mindent, ami a Pedestal
felett van!"
HOLOGRAM_PROJECTOR:
enter-text: "&7Kérlek, írd be a kívánt Hologram Szöveget a Chatbe. &r(A színkódok
enter-text: "&7Kérlek, írd be a kívánt hologram szöveget a chatre. &r(Színkódok
is használhatóak!)"
inventory-title: Hologram Szerkesztő
inventory-title: Hologram szerkesztő
ELEVATOR:
no-destinations: "&4Nem található úticél"
pick-a-floor: "&3- Válassz emeletet -"
current-floor: "&eEz az emelet, amelyen jelenleg tartózkodik:"
click-to-teleport: "&eKattints &7erre az emeletre való teleportáláshoz:"
enter-name: "&7Kérlek írd be a kívánt emelet nevet a Chatbe. &r(A Színkódok is
támogatottak!)"
current-floor: "&eEzen az emeleten tartózkodsz:"
click-to-teleport: "&eKattints&7, hogy erre az emeletre teleportálj:"
enter-name: "&7Kérlek írd be a kívánt emelet nevét a chatre. &r(Színkódok is használhatóak!)"
named: "&2Sikeresen elnevezted ezt az emeletet: &r%floor%"
TELEPORTER:
teleporting: "&3Teleportálás..."
@ -196,79 +222,81 @@ machines:
invulnerability: "&b&l30 másodperc Sérthetetlenséget kaptál!"
gui:
title: Az útpontjaid
tooltip: Klikk a teleportáláshoz
tooltip: Kattints a teleportáláshoz
time: Becsült idő
CARGO_NODES:
must-be-placed: "&4Ládára vagy gépre kell helyezni!"
GPS_CONTROL_PANEL:
title: GPS - Vezérlőpult
transmitters: Transzmitter Áttekintése
waypoints: Útpont Áttekintése
transmitters: Transzmitter áttekintése
waypoints: Útpont áttekintése
INDUSTRIAL_MINER:
no-fuel: "&cAz Ipari Bányászodnak elfogyott az üzemanyaga! Tedd az üzemanyagot
a fenti ládába."
piston-facing: "&cAz Ipari Bányászodhoz szükségesek dugattyúk, amik felfelé néznek!"
no-fuel: "&cAz Industrial Miner-ednek elfogyott az üzemanyaga! Tedd az üzemanyagot
a felette lévő ládába."
piston-facing: "&cAz Industrial Miner-edhez szükségesek dugattyúk, amik felfelé
néznek!"
piston-space: "&cA két dugattyú felett egy üres blokknak kell lennie!"
destroyed: "&cÚgy tűnik, hogy az Ipari Bányászod megsemmisült."
already-running: "&cEz az Ipari Bányász már fut!"
full-chest: "&cAz Ipari Bányász ládája tele van!"
no-permission: "&4Úgy tűnik, hogy nincs engedélyed az Ipari Bányász üzemeltetésére
destroyed: "&cÚgy tűnik, hogy az Industrial Miner-ed megsemmisült."
already-running: "&cEz az Industrial Miner már fut!"
full-chest: "&cAz Industrial Miner ládája tele van!"
no-permission: "&4Úgy tűnik, hogy nincs engedélyed Industrial Miner üzemeltetésére
itt!"
finished: Az Ipari Bányászod kész! Összesen %ores% ércet szerzett!
finished: Az Industrial Miner-ed kész! Összesen %ores% ércet szerzett!
anvil:
not-working: "&4Nem használhatsz Slimefun tárgyakat az Üllőben!"
not-working: "&4Nem használhatsz Slimefun tárgyakat az üllőben!"
backpack:
already-open: "&cSajnáljuk, ez a Hátizsák valahol máshol már nyitva van!"
no-stack: "&cNem lehet halmozni a Táskákat"
already-open: "&cSajnáljuk, ez a hátizsák valahol máshol már nyitva van!"
no-stack: "&cNem halmozhatsz hátizsákokat"
workbench:
not-enhanced: "&4Nem használhatsz Slimefun Tárgyakat normális barkácsasztalban"
not-enhanced: "&4Nem használhatsz Slimefun tárgyakat barkácsasztalban"
gps:
deathpoint: "&4Halálpont &7%date%"
deathpoint: "&4Halálpont: &7%date%"
waypoint:
new: "&eKérlek, add meg az új útpontot chatben. &7(A Színkódok használhatóak!)"
added: "&aSikeresen megadtad az útpontot"
new: "&eKérlek írd be az új útpont nevét chatre. &7(Színkódok használhatóak!)"
added: "&aSikeresen létrehoztál egy útpontot"
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%"
- "&4a) Még nem telepítetted a GPS Hálózatot"
- "&4b) A GPS Hálózatod nem eléggé összetett"
- "&4Nem megfelelő a GPS-hálózat komplexitása: &c%complexity%"
- "&4a) Még nem telepítetted a GPS-hálózatot"
- "&4b) A GPS-hálózatod nem eléggé összetett"
geo:
scan-required: "&4GEO-Vizsgálat szükséges! &cElőbb vizsgáld meg ezt a chunkot
a GEO-Szkennerrel!"
scan-required: "&4GEO-vizsgálat szükséges! &cElőbb vizsgáld meg ezt a chunkot
a GEO-Scannerrel!"
inventory:
no-access: "&4Nincs hozzáférésed ehhez a blokkhoz"
android:
started: "&7Az Androidod folytatja a szkript futtatását"
stopped: "&7Az Androidod szünetelteti a szkript futtatását"
started: "&7Az androidod folytatja a szkript futtatását"
stopped: "&7Az androidod szünetelteti a szkript futtatását"
scripts:
already-uploaded: "&4Ezt a szkriptet már feltöltötték."
instructions:
START: "&2Szkript indítása"
REPEAT: "&9Szkript ismétlése"
WAIT: "&eVárjon 0.5s"
WAIT: "&eVárj 5sodpercet"
GO_FORWARD: "&7Menj előre"
GO_UP: "&7Menj felfelé"
GO_DOWN: "&7Menj lefelé"
TURN_LEFT: "&7Fordulj balra"
TURN_RIGHT: "&7Fordulj jobbra"
DIG_UP: "&bÁss"
DIG_UP: "&bÁss felfelé"
DIG_FORWARD: "&bÁss előre"
DIG_DOWN: "&bÁss le"
MOVE_AND_DIG_UP: "&bMenj és Áss felfelé"
MOVE_AND_DIG_FORWARD: "&bMenj és Áss előre"
MOVE_AND_DIG_DOWN: "&bMenj és Áss lefelé"
ATTACK_MOBS_ANIMALS: "&4Támadj &c(Ellenséges Élőlények és Állatok)"
ATTACK_MOBS: "&4Támadj &c(Ellenséges Élőlények)"
ATTACK_ANIMALS: "&4Támadj &c(Állatok)"
ATTACK_ANIMALS_ADULT: "&4Támadj &c(Állatok &7[Felnőtt]&c)"
CHOP_TREE: "&cVágj és Ültess"
CATCH_FISH: "&bFogj Halat"
FARM_FORWARD: "&bSzüretelj és Ültess"
FARM_DOWN: "&bSzüretelj és Ültess &7(Blokk alatt)"
FARM_EXOTIC_FORWARD: "&bFejlett Szüretelés és Ültetés"
FARM_EXOTIC_DOWN: "&bFejlett Szüretelés és Ültetés &7(Blokk alatt)"
INTERFACE_ITEMS: "&9Tegye az Eszköztár Tartalmát a csatlakozási Felületbe"
INTERFACE_FUEL: "&cVegyen ki az Üzemanyagot a csatlakozási Felületről"
DIG_DOWN: "&bÁss lefelé"
MOVE_AND_DIG_UP: "&bMenj és áss felfelé"
MOVE_AND_DIG_FORWARD: "&bMenj és áss előre"
MOVE_AND_DIG_DOWN: "&bMenj és áss lefelé"
ATTACK_MOBS_ANIMALS: "&4Támadj &c(ellenséges élőlényeket és állatokat)"
ATTACK_MOBS: "&4Támadj &c(ellenséges élőlényeket)"
ATTACK_ANIMALS: "&4Támadj &c(állatokat)"
ATTACK_ANIMALS_ADULT: "&4Támadj &c(&7felnőtt &cállatokat)"
CHOP_TREE: "&cVágj fát és ültess"
CATCH_FISH: "&bFogj halat"
FARM_FORWARD: "&bSzüretelj és ültess"
FARM_DOWN: "&bSzüreteljen és ültessen &7(saját maga alatt)"
FARM_EXOTIC_FORWARD: "&bFejlett szüretelés és ültetés"
FARM_EXOTIC_DOWN: "&bFejlett szüretelés és ültetés &7(saját maga alatt)"
INTERFACE_ITEMS: "&9Tegye az eszköztár tartalmát a csatlakozási felületbe"
INTERFACE_FUEL: "&cVegyen ki az üzemanyagot a csatlakozási felületről"
enter-name:
-
- "&eKérlek, írd be a szkript nevét"
@ -280,7 +308,7 @@ android:
already: "&4Ezt a szkriptet már értékelted!"
editor: Szkript Szerkesztő
languages:
default: Szerver-Alapértelmezett
default: Szerver-alapértelmezett
en: Angol
de: Német
fr: Francia
@ -300,8 +328,9 @@ languages:
zh-CN: Kínai (Kína)
el: Görög
he: Héber
pt-BR: Portugál (Brazília)
ar: Arab
af: Afrikánsz
af: Afrikaans
da: Dán
fi: Finn
uk: Ukrán
@ -312,16 +341,19 @@ 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
hr: Horvát
mk: Macedóniai
mk: Macedón
sr: Szerb
be: Belorusz
be: Belarusz
tl: Tagalog
brewing_stand:
not-working: "&4Nem használhatsz Slimefun tárgyakat a Főzőállványban!"
not-working: "&4Nem használhatsz Slimefun tárgyakat főzőállványban!"
villagers:
no-trading: "&4Nem cserélhetsz Slimefun tárgyakat falusiakkal!"
cartography_table:
not-working: "&4Nem használhatsz Slimefun tárgyakat térképasztalban."
miner:
no-ores: "&eSajnálom, nem találtam semmilyen Ércet a közelben!"
no-ores: "&eSajnálom, nem találtam semmilyen ércet a közelben!"

Some files were not shown because too many files have changed in this diff Show More