mirror of
https://github.com/StarWishsama/Slimefun4.git
synced 2024-09-19 19:25:48 +00:00
Merge branch 'master' into fixes/blocks
This commit is contained in:
commit
cadf66a13c
3
.github/ISSUE_TEMPLATE/bug-report.md
vendored
3
.github/ISSUE_TEMPLATE/bug-report.md
vendored
@ -42,7 +42,7 @@ assignees: ''
|
||||
|
||||
|
||||
## :compass: Environment (REQUIRED)
|
||||
<!-- Any info without the exact version numbers will be closed! -->
|
||||
<!-- Any issue without the exact version numbers will be closed! -->
|
||||
<!-- "latest" IS NOT A VERSION NUMBER. -->
|
||||
<!-- We recommend running "/sf versions" and showing us a screenshot of that. -->
|
||||
<!-- Make sure that the screenshot covers the entire output of that command. -->
|
||||
@ -51,4 +51,3 @@ assignees: ''
|
||||
- Server Software:
|
||||
- Minecraft Version:
|
||||
- Slimefun Version:
|
||||
- CS-CoreLib Version:
|
||||
|
53
.github/workflows/pr-labels.yml
vendored
Normal file
53
.github/workflows/pr-labels.yml
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
name: Pull Request Labels
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
|
||||
jobs:
|
||||
pr-labeler:
|
||||
|
||||
name: Pull Request Labels
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'Slimefun/Slimefun4' && github.actor != 'gitlocalize-app[bot]' && github.actor != 'renovate[bot]'
|
||||
|
||||
steps:
|
||||
- uses: WalshyDev/pr-labels@v1.1
|
||||
id: labeller
|
||||
name: Apply labels based on branch
|
||||
with:
|
||||
token: "${{ secrets.ACCESS_TOKEN }}"
|
||||
feature: '🎈 Feature'
|
||||
fix: '✨ Fix'
|
||||
chore: '🧹 Chores'
|
||||
performance: '💡 Performance Optimization'
|
||||
api: '🔧 API'
|
||||
|
||||
- uses: thollander/actions-comment-pull-request@1.0.1
|
||||
name: Comment the applied label
|
||||
if: ${{ steps.labeller.outputs.applied != 0 }}
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
|
||||
message: |
|
||||
Your Pull Request was automatically labelled as: ${{ steps.labeller.outputs.applied }}
|
||||
Thank you for contributing to this project! ❤️
|
||||
|
||||
- uses: thollander/actions-comment-pull-request@1.0.1
|
||||
name: Comment the applied label
|
||||
if: ${{ steps.labeller.outputs.applied == 0 }}
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
|
||||
message: |
|
||||
**Pro Tip!**
|
||||
You can help us label your Pull Requests by using the following branch naming convention next time you create a pull request. ❤️
|
||||
Branch naming convention | Label
|
||||
------------------------ | ------
|
||||
`feature/**` | 🎈 Feature
|
||||
`fix/**` | ✨ Fix
|
||||
`chore/**` | 🧹 Chores
|
||||
`api/**` | 🔧 API
|
||||
`performance/**` | 💡 Performance Optimization
|
||||
<hr>
|
||||
If your changes do not fall into any of these categories, don't worry.
|
||||
You can just ignore this message in that case! 👀
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,10 +4,12 @@
|
||||
/sonar/
|
||||
/.settings/
|
||||
/.idea/
|
||||
/.vscode/
|
||||
|
||||
dependency-reduced-pom.xml
|
||||
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
*.iml
|
||||
.DS_Store
|
12
CHANGELOG.md
12
CHANGELOG.md
@ -28,10 +28,16 @@
|
||||
|
||||
#### Additions
|
||||
* Added a new language: Bulgarian
|
||||
* Added a new language: Hebrew
|
||||
* (API) Added AsyncProfileLoadEvent
|
||||
* Added Talisman of the Wise
|
||||
* Added Book Binder
|
||||
* Added Tier 3 Electric Ore Grinder
|
||||
|
||||
#### Changes
|
||||
* (API) Improvements to the BlockBreakHandler
|
||||
* Massive performance improvements to holograms/armorstands
|
||||
* Slimefun no longer requires CS-CoreLib to be installed
|
||||
|
||||
#### Fixes
|
||||
* Fixed elevator floor order
|
||||
@ -48,6 +54,12 @@
|
||||
* Fixed some backpack opening issues
|
||||
* Fixed Infused Hopper picking up items with a max pickup delay
|
||||
* Fixed duplication issues related to holograms/armorstands
|
||||
* Fixed #2754
|
||||
* Fixed machines not respecting max size from inventories
|
||||
* Fixed #2761
|
||||
* Fixed #2460
|
||||
* Fixed #2760
|
||||
* Fixed #2771
|
||||
|
||||
## Release Candidate 19 (11 Jan 2021)
|
||||
|
||||
|
10
pom.xml
10
pom.xml
@ -23,7 +23,7 @@
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
|
||||
<!-- Spigot properties -->
|
||||
<spigot.version>1.16.4</spigot.version>
|
||||
<spigot.version>1.16.5</spigot.version>
|
||||
<spigot.javadocs>https://hub.spigotmc.org/javadocs/spigot/</spigot.javadocs>
|
||||
|
||||
<!-- Default settings for sonarcloud.io -->
|
||||
@ -302,12 +302,6 @@
|
||||
<version>${spigot.version}-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.TheBusyBiscuit</groupId>
|
||||
<artifactId>CS-CoreLib</artifactId>
|
||||
<version>1.7</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Development dependencies -->
|
||||
<dependency>
|
||||
@ -393,7 +387,7 @@
|
||||
<dependency>
|
||||
<groupId>com.gmail.nossr50.mcMMO</groupId>
|
||||
<artifactId>mcMMO</artifactId>
|
||||
<version>2.1.171</version>
|
||||
<version>2.1.173</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
@ -149,7 +149,6 @@ public class ErrorReport<T extends Throwable> {
|
||||
stream.println();
|
||||
|
||||
stream.println("Slimefun Environment:");
|
||||
stream.println(" CS-CoreLib v" + SlimefunPlugin.getCSCoreLibVersion());
|
||||
stream.println(" Slimefun v" + SlimefunPlugin.getVersion());
|
||||
stream.println(" Caused by: " + addon.getName() + " v" + addon.getPluginVersion());
|
||||
stream.println();
|
||||
|
@ -0,0 +1,75 @@
|
||||
package io.github.thebusybiscuit.slimefun4.api.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
|
||||
|
||||
/**
|
||||
* This {@link Event} is called when the {@link PlayerProfile} of a {@link Player}
|
||||
* is loaded into memory.
|
||||
* The {@link AsyncProfileLoadEvent} is called asynchronously and can be used to "inject"
|
||||
* a custom {@link PlayerProfile} if necessary.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
* @see PlayerProfile
|
||||
*
|
||||
*/
|
||||
public class AsyncProfileLoadEvent extends Event {
|
||||
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final UUID uniqueId;
|
||||
private PlayerProfile profile;
|
||||
|
||||
public AsyncProfileLoadEvent(@Nonnull PlayerProfile profile) {
|
||||
super(true);
|
||||
|
||||
Validate.notNull(profile, "The Profile cannot be null");
|
||||
|
||||
this.uniqueId = profile.getUUID();
|
||||
this.profile = profile;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public UUID getPlayerUUID() {
|
||||
return uniqueId;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public PlayerProfile getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method can be used to inject your custom {@link PlayerProfile} implementations.
|
||||
* However, the passed {@link PlayerProfile} must have the same {@link UUID} as the original one!
|
||||
*
|
||||
* @param profile
|
||||
* The {@link PlayerProfile}
|
||||
*/
|
||||
public void setProfile(@Nonnull PlayerProfile profile) {
|
||||
Validate.notNull(profile, "The PlayerProfile cannot be null!");
|
||||
Validate.isTrue(profile.getUUID().equals(uniqueId), "Cannot inject a PlayerProfile with a different UUID");
|
||||
|
||||
this.profile = profile;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return getHandlerList();
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package io.github.thebusybiscuit.slimefun4.api.events;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
@ -27,8 +28,11 @@ public class ResearchUnlockEvent extends Event implements Cancellable {
|
||||
private boolean cancelled;
|
||||
|
||||
public ResearchUnlockEvent(@Nonnull Player p, @Nonnull Research research) {
|
||||
super(!Bukkit.isPrimaryThread());
|
||||
|
||||
Validate.notNull(p, "The Player cannot be null");
|
||||
Validate.notNull(research, "Research cannot be null");
|
||||
|
||||
this.player = p;
|
||||
this.research = research;
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
package io.github.thebusybiscuit.slimefun4.api.items;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
@ -92,7 +90,7 @@ public class ItemSetting<T> {
|
||||
*/
|
||||
@Nonnull
|
||||
public T getValue() {
|
||||
Validate.notNull(value, "An ItemSetting was invoked but was not initialized yet.");
|
||||
Validate.notNull(value, "ItemSetting '" + key + "' was invoked but was not initialized yet.");
|
||||
|
||||
return value;
|
||||
}
|
||||
@ -137,6 +135,7 @@ public class ItemSetting<T> {
|
||||
* @param item
|
||||
* The {@link SlimefunItem} who called this method
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void load(@Nonnull SlimefunItem item) {
|
||||
Validate.notNull(item, "Cannot apply settings for a non-existing SlimefunItem");
|
||||
|
||||
@ -144,26 +143,33 @@ public class ItemSetting<T> {
|
||||
Object configuredValue = SlimefunPlugin.getItemCfg().getValue(item.getId() + '.' + getKey());
|
||||
|
||||
if (defaultValue.getClass().isInstance(configuredValue)) {
|
||||
// We can suppress the warning here, we did an isInstance(...) check before!
|
||||
@SuppressWarnings("unchecked")
|
||||
// We can unsafe cast here, we did an isInstance(...) check before!
|
||||
T newValue = (T) configuredValue;
|
||||
|
||||
if (validateInput(newValue)) {
|
||||
this.value = newValue;
|
||||
} else {
|
||||
SlimefunPlugin.logger().log(Level.WARNING, "Slimefun has found an invalid config setting in your Items.yml!");
|
||||
SlimefunPlugin.logger().log(Level.WARNING, " at \"{0}.{1}\"", new Object[] { item.getId(), getKey() });
|
||||
SlimefunPlugin.logger().log(Level.WARNING, "{0} is not a valid input!", configuredValue);
|
||||
SlimefunPlugin.logger().log(Level.WARNING, getErrorMessage());
|
||||
// @formatter:off
|
||||
item.warn(
|
||||
"We have found an invalid config setting in your Items.yml!" +
|
||||
"\n at \"" + item.getId() + "." + getKey() + "\"" +
|
||||
"\n " + configuredValue + " is not a valid input!" +
|
||||
"\n" + getErrorMessage()
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
} else {
|
||||
this.value = defaultValue;
|
||||
String found = configuredValue == null ? "null" : configuredValue.getClass().getSimpleName();
|
||||
|
||||
SlimefunPlugin.logger().log(Level.WARNING, "Slimefun has found an invalid config setting in your Items.yml!");
|
||||
SlimefunPlugin.logger().log(Level.WARNING, "Please only use settings that are valid.");
|
||||
SlimefunPlugin.logger().log(Level.WARNING, " at \"{0}.{1}\"", new Object[] { item.getId(), getKey() });
|
||||
SlimefunPlugin.logger().log(Level.WARNING, "Expected \"{0}\" but found: \"{1}\"", new Object[] { defaultValue.getClass().getSimpleName(), found });
|
||||
// @formatter:off
|
||||
item.warn(
|
||||
"We have found an invalid config setting in your Items.yml!" +
|
||||
"\nPlease only use settings that are valid." +
|
||||
"\n at \"" + item.getId() + "." + getKey() + "\"" +
|
||||
"\n Expected \"" + defaultValue.getClass().getSimpleName() + "\" but found: \"" + found + "\""
|
||||
);
|
||||
// @formatter:on
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package io.github.thebusybiscuit.slimefun4.api.player;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@ -33,6 +32,7 @@ import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
|
||||
import io.github.thebusybiscuit.cscorelib2.config.Config;
|
||||
import io.github.thebusybiscuit.slimefun4.api.events.AsyncProfileLoadEvent;
|
||||
import io.github.thebusybiscuit.slimefun4.api.gps.Waypoint;
|
||||
import io.github.thebusybiscuit.slimefun4.api.items.HashedArmorpiece;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectionType;
|
||||
@ -56,7 +56,7 @@ import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
|
||||
* @see HashedArmorpiece
|
||||
*
|
||||
*/
|
||||
public final class PlayerProfile {
|
||||
public class PlayerProfile {
|
||||
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
@ -74,13 +74,17 @@ public final class PlayerProfile {
|
||||
|
||||
private final HashedArmorpiece[] armor = { new HashedArmorpiece(), new HashedArmorpiece(), new HashedArmorpiece(), new HashedArmorpiece() };
|
||||
|
||||
private PlayerProfile(@Nonnull OfflinePlayer p) {
|
||||
protected PlayerProfile(@Nonnull OfflinePlayer p) {
|
||||
this.uuid = p.getUniqueId();
|
||||
this.name = p.getName();
|
||||
|
||||
configFile = new Config(new File("data-storage/Slimefun/Players/" + uuid.toString() + ".yml"));
|
||||
configFile = new Config("data-storage/Slimefun/Players/" + uuid.toString() + ".yml");
|
||||
waypointsFile = new Config("data-storage/Slimefun/waypoints/" + uuid.toString() + ".yml");
|
||||
|
||||
loadProfileData();
|
||||
}
|
||||
|
||||
private void loadProfileData() {
|
||||
for (Research research : SlimefunPlugin.getRegistry().getResearches()) {
|
||||
if (configFile.contains("researches." + research.getID())) {
|
||||
researches.add(research);
|
||||
@ -95,7 +99,7 @@ public final class PlayerProfile {
|
||||
waypoints.add(new Waypoint(this, key, loc, waypointName));
|
||||
}
|
||||
} catch (Exception x) {
|
||||
SlimefunPlugin.logger().log(Level.WARNING, x, () -> "Could not load Waypoint \"" + key + "\" for Player \"" + p.getName() + '"');
|
||||
SlimefunPlugin.logger().log(Level.WARNING, x, () -> "Could not load Waypoint \"" + key + "\" for Player \"" + name + '"');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -268,14 +272,14 @@ public final class PlayerProfile {
|
||||
* Call this method if the Player has left.
|
||||
* The profile can then be removed from RAM.
|
||||
*/
|
||||
public void markForDeletion() {
|
||||
public final void markForDeletion() {
|
||||
markedForDeletion = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this method if this Profile has unsaved changes.
|
||||
*/
|
||||
public void markDirty() {
|
||||
public final void markDirty() {
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
@ -382,9 +386,11 @@ public final class PlayerProfile {
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().runTaskAsynchronously(SlimefunPlugin.instance(), () -> {
|
||||
PlayerProfile pp = new PlayerProfile(p);
|
||||
SlimefunPlugin.getRegistry().getPlayerProfiles().put(uuid, pp);
|
||||
callback.accept(pp);
|
||||
AsyncProfileLoadEvent event = new AsyncProfileLoadEvent(new PlayerProfile(p));
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
|
||||
SlimefunPlugin.getRegistry().getPlayerProfiles().put(uuid, event.getProfile());
|
||||
callback.accept(event.getProfile());
|
||||
});
|
||||
|
||||
return false;
|
||||
|
@ -1,6 +1,7 @@
|
||||
package io.github.thebusybiscuit.slimefun4.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@ -61,7 +62,7 @@ public final class SlimefunRegistry {
|
||||
|
||||
private final List<Research> researches = new LinkedList<>();
|
||||
private final List<String> researchRanks = new ArrayList<>();
|
||||
private final Set<UUID> researchingPlayers = new HashSet<>();
|
||||
private final Set<UUID> researchingPlayers = Collections.synchronizedSet(new HashSet<>());
|
||||
|
||||
private boolean backwardsCompatibility;
|
||||
private boolean automaticallyLoadItems;
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.github.thebusybiscuit.slimefun4.core.attributes;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.utils.ChargeUtils;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -57,7 +58,7 @@ public interface Rechargeable extends ItemAttribute {
|
||||
}
|
||||
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
RechargeableHelper.setCharge(meta, charge, maximum);
|
||||
ChargeUtils.setCharge(meta, charge, maximum);
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
|
||||
@ -74,7 +75,7 @@ public interface Rechargeable extends ItemAttribute {
|
||||
throw new IllegalArgumentException("Cannot get Item charge for null or AIR");
|
||||
}
|
||||
|
||||
return RechargeableHelper.getCharge(item.getItemMeta());
|
||||
return ChargeUtils.getCharge(item.getItemMeta());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,7 +98,7 @@ public interface Rechargeable extends ItemAttribute {
|
||||
}
|
||||
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
float currentCharge = RechargeableHelper.getCharge(meta);
|
||||
float currentCharge = ChargeUtils.getCharge(meta);
|
||||
float maximum = getMaxItemCharge(item);
|
||||
|
||||
// If the item is already fully charged, we abort.
|
||||
@ -106,7 +107,7 @@ public interface Rechargeable extends ItemAttribute {
|
||||
}
|
||||
|
||||
float newCharge = Math.min(currentCharge + charge, maximum);
|
||||
RechargeableHelper.setCharge(meta, newCharge, maximum);
|
||||
ChargeUtils.setCharge(meta, newCharge, maximum);
|
||||
|
||||
item.setItemMeta(meta);
|
||||
return true;
|
||||
@ -132,7 +133,7 @@ public interface Rechargeable extends ItemAttribute {
|
||||
}
|
||||
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
float currentCharge = RechargeableHelper.getCharge(meta);
|
||||
float currentCharge = ChargeUtils.getCharge(meta);
|
||||
|
||||
// If the item does not have enough charge, we abort
|
||||
if (currentCharge < charge) {
|
||||
@ -140,7 +141,7 @@ public interface Rechargeable extends ItemAttribute {
|
||||
}
|
||||
|
||||
float newCharge = Math.max(currentCharge - charge, 0);
|
||||
RechargeableHelper.setCharge(meta, newCharge, getMaxItemCharge(item));
|
||||
ChargeUtils.setCharge(meta, newCharge, getMaxItemCharge(item));
|
||||
|
||||
item.setItemMeta(meta);
|
||||
return true;
|
||||
|
@ -30,7 +30,6 @@ class VersionsCommand extends SubCommand {
|
||||
|
||||
sender.sendMessage(ChatColor.GRAY + "This Server uses the following setup of Slimefun:");
|
||||
sender.sendMessage(ChatColors.color("&a" + serverSoftware + " &2" + Bukkit.getVersion()));
|
||||
sender.sendMessage(ChatColors.color("&aCS-CoreLib &2v" + SlimefunPlugin.getCSCoreLibVersion()));
|
||||
sender.sendMessage(ChatColors.color("&aSlimefun &2v" + SlimefunPlugin.getVersion()));
|
||||
|
||||
if (SlimefunPlugin.getMetricsService().getVersion() != null) {
|
||||
|
@ -4,6 +4,9 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
@ -14,6 +17,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
|
||||
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
|
||||
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
|
||||
import io.github.thebusybiscuit.slimefun4.core.services.localization.Language;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
|
||||
@ -46,10 +50,11 @@ public final class SlimefunGuideSettings {
|
||||
|
||||
private SlimefunGuideSettings() {}
|
||||
|
||||
public static <T> void addOption(SlimefunGuideOption<T> option) {
|
||||
public static <T> void addOption(@Nonnull SlimefunGuideOption<T> option) {
|
||||
options.add(option);
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public static void openSettings(Player p, ItemStack guide) {
|
||||
ChestMenu menu = new ChestMenu(SlimefunPlugin.getLocalization().getMessage(p, "guide.title.settings"));
|
||||
|
||||
@ -64,6 +69,7 @@ public final class SlimefunGuideSettings {
|
||||
menu.open(p);
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
private static void addHeader(Player p, ChestMenu menu, ItemStack guide) {
|
||||
menu.addItem(0, new CustomItem(SlimefunGuide.getItem(SlimefunGuideMode.SURVIVAL_MODE), "&e\u21E6 " + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.title"), "", "&7" + SlimefunPlugin.getLocalization().getMessage(p, "guide.back.guide")), (pl, slot, item, action) -> {
|
||||
SlimefunGuide.openGuide(pl, guide);
|
||||
@ -81,7 +87,7 @@ public final class SlimefunGuideSettings {
|
||||
return false;
|
||||
});
|
||||
|
||||
menu.addItem(4, new CustomItem(Material.WRITABLE_BOOK, ChatColor.GREEN + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.versions"), "&7&o" + SlimefunPlugin.getLocalization().getMessage(p, "guide.tooltips.versions-notice"), "", "&fMinecraft: &a" + Bukkit.getBukkitVersion(), "&fSlimefun: &a" + SlimefunPlugin.getVersion(), "&fCS-CoreLib: &a" + SlimefunPlugin.getCSCoreLibVersion()), ChestMenuUtils.getEmptyClickHandler());
|
||||
menu.addItem(4, new CustomItem(Material.WRITABLE_BOOK, ChatColor.GREEN + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.versions"), "&7&o" + SlimefunPlugin.getLocalization().getMessage(p, "guide.tooltips.versions-notice"), "", "&fMinecraft: &a" + Bukkit.getBukkitVersion(), "&fSlimefun: &a" + SlimefunPlugin.getVersion()), ChestMenuUtils.getEmptyClickHandler());
|
||||
|
||||
menu.addItem(6,
|
||||
new CustomItem(Material.COMPARATOR, "&e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.source"), "", "&7Last Activity: &a" + NumberUtils.getElapsedTime(SlimefunPlugin.getGitHubService().getLastUpdate()) + " ago", "&7Forks: &e" + SlimefunPlugin.getGitHubService().getForks(), "&7Stars: &e" + SlimefunPlugin.getGitHubService().getStars(), "", "&7&oSlimefun 4 is a community project,", "&7&othe source code is available on GitHub", "&7&oand if you want to keep this Plugin alive,", "&7&othen please consider contributing to it", "", "&7\u21E8 &eClick to go to GitHub"));
|
||||
@ -119,6 +125,7 @@ public final class SlimefunGuideSettings {
|
||||
});
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
private static void addConfigurableOptions(Player p, ChestMenu menu, ItemStack guide) {
|
||||
int i = 19;
|
||||
|
||||
@ -137,7 +144,17 @@ public final class SlimefunGuideSettings {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasFireworksEnabled(Player p) {
|
||||
/**
|
||||
* This method checks if the given {@link Player} has enabled the {@link FireworksOption}
|
||||
* in their {@link SlimefunGuide}.
|
||||
* If they enabled this setting, they will see fireworks when they unlock a {@link Research}.
|
||||
*
|
||||
* @param p
|
||||
* The {@link Player}
|
||||
*
|
||||
* @return Whether this {@link Player} wants to see fireworks when unlocking a {@link Research}
|
||||
*/
|
||||
public static boolean hasFireworksEnabled(@Nonnull Player p) {
|
||||
for (SlimefunGuideOption<?> option : options) {
|
||||
if (option instanceof FireworksOption) {
|
||||
FireworksOption fireworks = (FireworksOption) option;
|
||||
|
@ -0,0 +1,129 @@
|
||||
package io.github.thebusybiscuit.slimefun4.core.researching;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.api.events.ResearchUnlockEvent;
|
||||
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
|
||||
import io.github.thebusybiscuit.slimefun4.core.guide.options.SlimefunGuideSettings;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.FireworkUtils;
|
||||
|
||||
/**
|
||||
* A {@link PlayerResearchTask} is run when a {@link Player} unlocks a {@link Research}.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
*
|
||||
* @see Research
|
||||
* @see ResearchUnlockEvent
|
||||
* @see PlayerProfile
|
||||
*
|
||||
*/
|
||||
public class PlayerResearchTask implements Consumer<PlayerProfile> {
|
||||
|
||||
private static final int[] RESEARCH_PROGRESS = { 23, 44, 57, 92 };
|
||||
private static final String PLACEHOLDER = "%research%";
|
||||
|
||||
private final Research research;
|
||||
private final boolean isInstant;
|
||||
private final Consumer<Player> callback;
|
||||
|
||||
/**
|
||||
* This constructs a new {@link PlayerResearchTask}.
|
||||
*
|
||||
* @param research
|
||||
* The {@link Research} to unlock
|
||||
* @param isInstant
|
||||
* Whether to unlock this {@link Research} instantaneously
|
||||
* @param callback
|
||||
* The callback to run when the task has completed
|
||||
*/
|
||||
PlayerResearchTask(@Nonnull Research research, boolean isInstant, @Nullable Consumer<Player> callback) {
|
||||
Validate.notNull(research, "The Research must not be null");
|
||||
|
||||
this.research = research;
|
||||
this.isInstant = isInstant;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(PlayerProfile profile) {
|
||||
if (!profile.hasUnlocked(research)) {
|
||||
Player p = profile.getPlayer();
|
||||
|
||||
if (p == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isInstant) {
|
||||
SlimefunPlugin.runSync(() -> {
|
||||
p.playSound(p.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 0.7F, 1F);
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "messages.research.progress", true, msg -> msg.replace(PLACEHOLDER, research.getName(p)).replace("%progress%", "0%"));
|
||||
}, 5L);
|
||||
}
|
||||
|
||||
ResearchUnlockEvent event = new ResearchUnlockEvent(p, research);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
|
||||
if (!event.isCancelled()) {
|
||||
if (isInstant) {
|
||||
SlimefunPlugin.runSync(() -> unlockResearch(p, profile));
|
||||
} else if (SlimefunPlugin.getRegistry().getCurrentlyResearchingPlayers().add(p.getUniqueId())) {
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "messages.research.start", true, msg -> msg.replace(PLACEHOLDER, research.getName(p)));
|
||||
sendUpdateMessage(p);
|
||||
|
||||
SlimefunPlugin.runSync(() -> {
|
||||
unlockResearch(p, profile);
|
||||
SlimefunPlugin.getRegistry().getCurrentlyResearchingPlayers().remove(p.getUniqueId());
|
||||
}, (RESEARCH_PROGRESS.length + 1) * 20L);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendUpdateMessage(@Nonnull Player p) {
|
||||
for (int i = 1; i < RESEARCH_PROGRESS.length + 1; i++) {
|
||||
int index = i;
|
||||
|
||||
SlimefunPlugin.runSync(() -> {
|
||||
p.playSound(p.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 0.7F, 1);
|
||||
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "messages.research.progress", true, msg -> {
|
||||
String progress = RESEARCH_PROGRESS[index - 1] + "%";
|
||||
return msg.replace(PLACEHOLDER, research.getName(p)).replace("%progress%", progress);
|
||||
});
|
||||
}, i * 20L);
|
||||
}
|
||||
}
|
||||
|
||||
private void unlockResearch(@Nonnull Player p, @Nonnull PlayerProfile profile) {
|
||||
profile.setResearched(research, true);
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "messages.unlocked", true, msg -> msg.replace(PLACEHOLDER, research.getName(p)));
|
||||
onFinish(p);
|
||||
|
||||
// Check if the Server and the Player have enabled fireworks for researches
|
||||
if (SlimefunPlugin.getRegistry().isResearchFireworkEnabled() && SlimefunGuideSettings.hasFireworksEnabled(p)) {
|
||||
FireworkUtils.launchRandom(p, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when the {@link Research} successfully finished to unlock.
|
||||
*
|
||||
* @param p
|
||||
* The {@link Player} who has unlocked this {@link Research}
|
||||
*/
|
||||
private void onFinish(@Nonnull Player p) {
|
||||
if (callback != null) {
|
||||
callback.accept(p);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -15,19 +15,16 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Keyed;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.api.events.PlayerPreResearchEvent;
|
||||
import io.github.thebusybiscuit.slimefun4.api.events.ResearchUnlockEvent;
|
||||
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
|
||||
import io.github.thebusybiscuit.slimefun4.core.guide.options.SlimefunGuideSettings;
|
||||
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideImplementation;
|
||||
import io.github.thebusybiscuit.slimefun4.core.services.localization.Language;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.setup.ResearchSetup;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.FireworkUtils;
|
||||
import io.github.thebusybiscuit.slimefun4.api.events.PlayerPreResearchEvent;
|
||||
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideImplementation;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
|
||||
@ -43,9 +40,6 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
*/
|
||||
public class Research implements Keyed {
|
||||
|
||||
private static final int[] RESEARCH_PROGRESS = { 23, 44, 57, 92 };
|
||||
private static final String PLACEHOLDER_RESEARCH = "%research%";
|
||||
|
||||
private final NamespacedKey key;
|
||||
private final int id;
|
||||
private final String name;
|
||||
@ -258,7 +252,7 @@ public class Research implements Keyed {
|
||||
* Whether to unlock it instantly
|
||||
*/
|
||||
public void unlock(@Nonnull Player p, boolean instant) {
|
||||
unlock(p, instant, pl -> {});
|
||||
unlock(p, instant, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -266,62 +260,13 @@ public class Research implements Keyed {
|
||||
*
|
||||
* @param p
|
||||
* The {@link Player} for which to unlock this {@link Research}
|
||||
* @param instant
|
||||
* @param isInstant
|
||||
* Whether to unlock this {@link Research} instantly
|
||||
* @param callback
|
||||
* A callback which will be run when the {@link Research} animation completed
|
||||
*/
|
||||
public void unlock(@Nonnull Player p, boolean instant, @Nonnull Consumer<Player> callback) {
|
||||
if (!instant) {
|
||||
SlimefunPlugin.runSync(() -> {
|
||||
p.playSound(p.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 0.7F, 1F);
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "messages.research.progress", true, msg -> msg.replace(PLACEHOLDER_RESEARCH, getName(p)).replace("%progress%", "0%"));
|
||||
}, 10L);
|
||||
}
|
||||
|
||||
PlayerProfile.get(p, profile -> {
|
||||
if (!profile.hasUnlocked(this)) {
|
||||
SlimefunPlugin.runSync(() -> {
|
||||
ResearchUnlockEvent event = new ResearchUnlockEvent(p, this);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
|
||||
if (!event.isCancelled()) {
|
||||
if (instant) {
|
||||
finishResearch(p, profile, callback);
|
||||
} else if (SlimefunPlugin.getRegistry().getCurrentlyResearchingPlayers().add(p.getUniqueId())) {
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "messages.research.start", true, msg -> msg.replace(PLACEHOLDER_RESEARCH, getName(p)));
|
||||
playResearchAnimation(p);
|
||||
|
||||
SlimefunPlugin.runSync(() -> {
|
||||
finishResearch(p, profile, callback);
|
||||
SlimefunPlugin.getRegistry().getCurrentlyResearchingPlayers().remove(p.getUniqueId());
|
||||
}, (RESEARCH_PROGRESS.length + 1) * 20L);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void finishResearch(@Nonnull Player p, @Nonnull PlayerProfile profile, @Nonnull Consumer<Player> callback) {
|
||||
profile.setResearched(this, true);
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "messages.unlocked", true, msg -> msg.replace(PLACEHOLDER_RESEARCH, getName(p)));
|
||||
callback.accept(p);
|
||||
|
||||
if (SlimefunPlugin.getRegistry().isResearchFireworkEnabled() && SlimefunGuideSettings.hasFireworksEnabled(p)) {
|
||||
FireworkUtils.launchRandom(p, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void playResearchAnimation(@Nonnull Player p) {
|
||||
for (int i = 1; i < RESEARCH_PROGRESS.length + 1; i++) {
|
||||
int j = i;
|
||||
|
||||
SlimefunPlugin.runSync(() -> {
|
||||
p.playSound(p.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 0.7F, 1F);
|
||||
SlimefunPlugin.getLocalization().sendMessage(p, "messages.research.progress", true, msg -> msg.replace(PLACEHOLDER_RESEARCH, getName(p)).replace("%progress%", RESEARCH_PROGRESS[j - 1] + "%"));
|
||||
}, i * 20L);
|
||||
}
|
||||
public void unlock(@Nonnull Player p, boolean isInstant, @Nullable Consumer<Player> callback) {
|
||||
PlayerProfile.get(p, new PlayerResearchTask(this, isInstant, callback));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -329,7 +274,6 @@ public class Research implements Keyed {
|
||||
*/
|
||||
public void register() {
|
||||
SlimefunPlugin.getResearchCfg().setDefaultValue("enable-researching", true);
|
||||
|
||||
String path = key.getNamespace() + '.' + key.getKey();
|
||||
|
||||
if (SlimefunPlugin.getResearchCfg().contains(path + ".enabled") && !SlimefunPlugin.getResearchCfg().getBoolean(path + ".enabled")) {
|
||||
|
@ -47,7 +47,7 @@ enum SupportedLanguage {
|
||||
CHINESE_TAIWAN("zh-TW", true, "702a4afb2e1e2e3a1894a8b74272f95cfa994ce53907f9ac140bd3c932f9f"),
|
||||
JAPANESE("ja", true, "d640ae466162a47d3ee33c4076df1cab96f11860f07edb1f0832c525a9e33323"),
|
||||
KOREAN("ko", true, "fc1be5f12f45e413eda56f3de94e08d90ede8e339c7b1e8f32797390e9a5f"),
|
||||
HEBREW("he", false, "1ba086a2cc7272cf5ba49c80248546c22e5ef1bab54120e8a8e5d9e75b6a"),
|
||||
HEBREW("he", true, "1ba086a2cc7272cf5ba49c80248546c22e5ef1bab54120e8a8e5d9e75b6a"),
|
||||
ARABIC("ar", true, "a4be759a9cf7f0a19a7e8e62f23789ad1d21cebae38af9d9541676a3db001572"),
|
||||
TURKISH("tr", true, "9852b9aba3482348514c1034d0affe73545c9de679ae4647f99562b5e5f47d09"),
|
||||
PERSIAN("fa", false, "5cd9badf1972583b663b44b1e027255de8f275aa1e89defcf77782ba6fcc652"),
|
||||
|
@ -47,6 +47,14 @@ public class Translators {
|
||||
addTranslator("dracrus", SupportedLanguage.ITALIAN, true);
|
||||
addTranslator("prolletto64", SupportedLanguage.ITALIAN, true);
|
||||
|
||||
// Translators - Spanish
|
||||
addTranslator("Luu7", "_Luu", SupportedLanguage.SPANISH, true);
|
||||
addTranslator("Vravinite", SupportedLanguage.SPANISH, true);
|
||||
addTranslator("NotUmBr4", SupportedLanguage.SPANISH, true);
|
||||
addTranslator("dbzjjoe", SupportedLanguage.SPANISH, true);
|
||||
addTranslator("DaHolyCheese", SupportedLanguage.SPANISH, true);
|
||||
addTranslator("d-l-n", SupportedLanguage.SPANISH, true);
|
||||
|
||||
// Translators - Latvian
|
||||
addTranslator("AgnisT", "NIKNAIZ", SupportedLanguage.LATVIAN, true);
|
||||
|
||||
@ -91,13 +99,6 @@ public class Translators {
|
||||
// Translators - Ukrainian
|
||||
addTranslator("SoSeDiK", SupportedLanguage.UKRAINIAN, false);
|
||||
|
||||
// Translators - Spanish
|
||||
addTranslator("Luu7", "_Luu", SupportedLanguage.SPANISH, true);
|
||||
addTranslator("Vravinite", SupportedLanguage.SPANISH, true);
|
||||
addTranslator("NotUmBr4", SupportedLanguage.SPANISH, true);
|
||||
addTranslator("dbzjjoe", SupportedLanguage.SPANISH, true);
|
||||
addTranslator("DaHolyCheese", SupportedLanguage.SPANISH, true);
|
||||
|
||||
// Translators - Swedish
|
||||
addTranslator("NihilistBrew", "ma1yang2", SupportedLanguage.SWEDISH, false);
|
||||
addTranslator("Tra-sh", "TurretTrash", SupportedLanguage.SWEDISH, true);
|
||||
@ -137,7 +138,9 @@ public class Translators {
|
||||
addTranslator("Eylonnn", SupportedLanguage.HEBREW, true);
|
||||
addTranslator("sarhatabaot", SupportedLanguage.HEBREW, false);
|
||||
addTranslator("Timotiyadeyhakesem", SupportedLanguage.HEBREW, true);
|
||||
addTranslator("PaladinBear", SupportedLanguage.HEBREW, true);
|
||||
addTranslator("Molioron", SupportedLanguage.HEBREW, true);
|
||||
addTranslator("McAlmog", SupportedLanguage.HEBREW, true);
|
||||
|
||||
// Translators - Japanese
|
||||
addTranslator("bito-blosh", "Bloshop", SupportedLanguage.JAPANESE, false);
|
||||
|
@ -562,6 +562,7 @@ public final class SlimefunItems {
|
||||
public static final SlimefunItemStack TALISMAN_WHIRLWIND = new SlimefunItemStack("WHIRLWIND_TALISMAN", Material.EMERALD, "&aTalisman of the Whirlwind", "", "&fHaving this Talisman", "&fin your Inventory will reflect", "&f60% of any projectiles fired at you.", "&e&oOnly a thrown Trident can pierce", "&e&othrough this layer of protection");
|
||||
public static final SlimefunItemStack TALISMAN_WIZARD = new SlimefunItemStack("WIZARD_TALISMAN", Material.EMERALD, "&aTalisman of the Wizard", "", "&fWhile you have this Talisman", "&fin your Inventory it allows you to", "&fobtain Fortune Level 4/5 however", "&fit also has a chance to lower the", "&fLevel of some Enchantments on your Item");
|
||||
public static final SlimefunItemStack TALISMAN_CAVEMAN = new SlimefunItemStack("CAVEMAN_TALISMAN", Material.EMERALD, "&aTalisman of the Caveman", "", "&fWhile you have this Talisman", "&fin your inventory it gives", "&fyou a 50% chance for a decent", "&fHaste buff when you mine any ore");
|
||||
public static final SlimefunItemStack TALISMAN_WISE = new SlimefunItemStack("WISE_TALISMAN", Material.EMERALD, "&aTalisman of the Wise", "", "&fWhile you have this Talisman", "&fin your inventory it gives", "&fyou a 20% chance of doubling", "&fany experience you obtain");
|
||||
|
||||
/* Staves */
|
||||
public static final SlimefunItemStack STAFF_ELEMENTAL = new SlimefunItemStack("STAFF_ELEMENTAL", Material.STICK, "&6Elemental Staff");
|
||||
@ -675,6 +676,7 @@ public final class SlimefunItems {
|
||||
|
||||
public static final SlimefunItemStack ELECTRIC_ORE_GRINDER = new SlimefunItemStack("ELECTRIC_ORE_GRINDER", Material.FURNACE, "&cElectric Ore Grinder", "", "&fWorks as an Ore Crusher and Grind Stone", "", LoreBuilder.machine(MachineTier.ADVANCED, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(12));
|
||||
public static final SlimefunItemStack ELECTRIC_ORE_GRINDER_2 = new SlimefunItemStack("ELECTRIC_ORE_GRINDER_2", Material.FURNACE, "&cElectric Ore Grinder &7(&eII&7)", "", "&fWorks as an Ore Crusher and Grind Stone", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), LoreBuilder.speed(4), LoreBuilder.powerPerSecond(30));
|
||||
public static final SlimefunItemStack ELECTRIC_ORE_GRINDER_3 = new SlimefunItemStack("ELECTRIC_ORE_GRINDER_3", Material.FURNACE, "&cElectric Ore Grinder &7(&eIII&7)", "", "&fWorks as an Ore Crusher and Grind Stone", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), LoreBuilder.speed(10), LoreBuilder.powerPerSecond(90));
|
||||
public static final SlimefunItemStack ELECTRIC_INGOT_PULVERIZER = new SlimefunItemStack("ELECTRIC_INGOT_PULVERIZER", Material.FURNACE, "&cElectric Ingot Pulverizer", "", "&fPulverizes Ingots into Dust", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(14));
|
||||
public static final SlimefunItemStack AUTO_DRIER = new SlimefunItemStack("AUTO_DRIER", Material.SMOKER, "&6Auto Drier", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(10));
|
||||
public static final SlimefunItemStack AUTO_ENCHANTER = new SlimefunItemStack("AUTO_ENCHANTER", Material.ENCHANTING_TABLE, "&5Auto Enchanter", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(18));
|
||||
@ -683,6 +685,8 @@ public final class SlimefunItems {
|
||||
public static final SlimefunItemStack AUTO_ANVIL_2 = new SlimefunItemStack("AUTO_ANVIL_2", Material.IRON_BLOCK, "&7Auto Anvil Mk.II", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), "&8\u21E8 &7Repair Factor: 25%", LoreBuilder.powerPerSecond(32));
|
||||
public static final SlimefunItemStack AUTO_BREWER = new SlimefunItemStack("AUTO_BREWER", Material.SMOKER, "&6Auto Brewer", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(12));
|
||||
|
||||
public static final SlimefunItemStack BOOK_BINDER = new SlimefunItemStack("BOOK_BINDER", Material.BOOKSHELF, "&6Book Binder", "", "&fBinds multiple enchanted books into one.", "", LoreBuilder.machine(MachineTier.MEDIUM, MachineType.MACHINE), LoreBuilder.powerPerSecond(16));
|
||||
|
||||
public static final SlimefunItemStack BIO_REACTOR = new SlimefunItemStack("BIO_REACTOR", Material.LIME_TERRACOTTA, "&2Bio Reactor", "", LoreBuilder.machine(MachineTier.AVERAGE, MachineType.GENERATOR), LoreBuilder.powerBuffer(128), LoreBuilder.powerPerSecond(8));
|
||||
public static final SlimefunItemStack MULTIMETER = new SlimefunItemStack("MULTIMETER", Material.CLOCK, "&eMultimeter", "", "&fMeasures the Amount of stored", "&fEnergy in a Block");
|
||||
|
||||
|
@ -118,6 +118,7 @@ import io.github.thebusybiscuit.slimefun4.integrations.IntegrationsManager;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.MenuListener;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator;
|
||||
import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
||||
@ -203,38 +204,17 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
||||
*/
|
||||
@Override
|
||||
public void onEnable() {
|
||||
if (minecraftVersion == MinecraftVersion.UNIT_TEST) {
|
||||
// We handle Unit Tests seperately.
|
||||
setInstance(this);
|
||||
|
||||
if (isUnitTest()) {
|
||||
// We handle Unit Tests seperately.
|
||||
onUnitTestStart();
|
||||
} else if (isVersionUnsupported()) {
|
||||
// We wanna ensure that the Server uses a compatible version of Minecraft.
|
||||
setInstance(this);
|
||||
getLogger().log(Level.WARNING, "Slimefun was not installed properly! Disabling...");
|
||||
getServer().getPluginManager().disablePlugin(this);
|
||||
} else if (getServer().getPluginManager().isPluginEnabled("CS-CoreLib")) {
|
||||
// The Environment and dependencies have been validated.
|
||||
setInstance(this);
|
||||
getLogger().log(Level.INFO, "CS-CoreLib was detected!");
|
||||
onPluginStart();
|
||||
} else {
|
||||
// Terminate our Plugin instance
|
||||
setInstance(null);
|
||||
|
||||
// CS-CoreLib has not been installed!
|
||||
getLogger().log(Level.INFO, "#################### - INFO - ####################");
|
||||
getLogger().log(Level.INFO, " ");
|
||||
getLogger().log(Level.INFO, "Slimefun could not be loaded (yet).");
|
||||
getLogger().log(Level.INFO, "It appears that you have not installed CS-CoreLib.");
|
||||
getLogger().log(Level.INFO, "Please download and install CS-CoreLib manually:");
|
||||
getLogger().log(Level.INFO, "https://thebusybiscuit.github.io/builds/TheBusyBiscuit/CS-CoreLib/master/");
|
||||
|
||||
// Send a message upon doing /slimefun
|
||||
getCommand("slimefun").setExecutor((sender, cmd, label, args) -> {
|
||||
sender.sendMessage("You have forgotten to install CS-CoreLib! Slimefun is disabled.");
|
||||
sender.sendMessage("https://thebusybiscuit.github.io/builds/TheBusyBiscuit/CS-CoreLib/master/");
|
||||
return true;
|
||||
});
|
||||
// The Environment has been validated.
|
||||
onPluginStart();
|
||||
}
|
||||
}
|
||||
|
||||
@ -457,7 +437,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
||||
long ms = (System.nanoTime() - timestamp) / 1000000;
|
||||
|
||||
if (ms > 1000) {
|
||||
return NumberUtils.roundDecimalNumber(ms / 1000.0) + "s";
|
||||
return NumberUtils.roundDecimalNumber(ms / 1000.0) + 's';
|
||||
} else {
|
||||
return NumberUtils.roundDecimalNumber(ms) + "ms";
|
||||
}
|
||||
@ -480,6 +460,16 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
||||
Reactor.progress = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks if this is currently running in a unit test
|
||||
* environment.
|
||||
*
|
||||
* @return Whether we are inside a unit test
|
||||
*/
|
||||
public boolean isUnitTest() {
|
||||
return minecraftVersion == MinecraftVersion.UNIT_TEST;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks for the {@link MinecraftVersion} of the {@link Server}.
|
||||
* If the version is unsupported, a warning will be printed to the console.
|
||||
@ -596,6 +586,9 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
||||
* This method registers all of our {@link Listener Listeners}.
|
||||
*/
|
||||
private void registerListeners() {
|
||||
// Old deprecated CS-CoreLib Listener
|
||||
new MenuListener(this);
|
||||
|
||||
new SlimefunBootsListener(this);
|
||||
new SlimefunItemInteractListener(this);
|
||||
new SlimefunItemConsumeListener(this);
|
||||
@ -984,18 +977,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
||||
return instance.isNewlyInstalled;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static String getCSCoreLibVersion() {
|
||||
validateInstance();
|
||||
Plugin cscorelib = instance.getServer().getPluginManager().getPlugin("CS-CoreLib");
|
||||
|
||||
if (cscorelib == null) {
|
||||
throw new IllegalStateException("CS-CoreLib is not installed.");
|
||||
} else {
|
||||
return cscorelib.getDescription().getVersion();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a {@link Set} of every {@link Plugin} that lists Slimefun
|
||||
* as a required or optional dependency.
|
||||
|
@ -0,0 +1,142 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.inventory.InvUtils;
|
||||
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
|
||||
import io.github.thebusybiscuit.slimefun4.api.items.settings.IntRangeSetting;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
|
||||
|
||||
/**
|
||||
* Represents Book Binder, a machine that binds multiple enchantments books into one.
|
||||
*
|
||||
* @author ProfElements
|
||||
*/
|
||||
public class BookBinder extends AContainer {
|
||||
|
||||
private final ItemSetting<Boolean> bypassVanillaMaxLevel = new ItemSetting<>("bypass-vanilla-max-level", false);
|
||||
private final ItemSetting<Boolean> hasCustomMaxLevel = new ItemSetting<>("has-custom-max-level", false);
|
||||
private final ItemSetting<Integer> customMaxLevel = new IntRangeSetting("custom-max-level", 0, 15, Integer.MAX_VALUE);
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public BookBinder(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
|
||||
addItemSetting(bypassVanillaMaxLevel, hasCustomMaxLevel, customMaxLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MachineRecipe findNextRecipe(BlockMenu menu) {
|
||||
for (int slot : getInputSlots()) {
|
||||
ItemStack target = menu.getItemInSlot(slot == getInputSlots()[0] ? getInputSlots()[1] : getInputSlots()[0]);
|
||||
ItemStack item = menu.getItemInSlot(slot);
|
||||
|
||||
if (isCompatible(item) && isCompatible(target)) {
|
||||
EnchantmentStorageMeta itemMeta = (EnchantmentStorageMeta) item.getItemMeta();
|
||||
EnchantmentStorageMeta targetMeta = (EnchantmentStorageMeta) target.getItemMeta();
|
||||
|
||||
Map<Enchantment, Integer> storedItemEnchantments = itemMeta.getStoredEnchants();
|
||||
Map<Enchantment, Integer> storedTargetEnchantments = targetMeta.getStoredEnchants();
|
||||
Map<Enchantment, Integer> enchantments = combineEnchantments(storedItemEnchantments, storedTargetEnchantments);
|
||||
|
||||
if (enchantments.size() > 0) {
|
||||
ItemStack book = new ItemStack(Material.ENCHANTED_BOOK);
|
||||
|
||||
EnchantmentStorageMeta enchantMeta = (EnchantmentStorageMeta) book.getItemMeta();
|
||||
|
||||
for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
|
||||
enchantMeta.addStoredEnchant(entry.getKey(), entry.getValue(), bypassVanillaMaxLevel.getValue());
|
||||
}
|
||||
|
||||
book.setItemMeta(enchantMeta);
|
||||
|
||||
MachineRecipe recipe = new MachineRecipe(25 * (enchantments.size() / this.getSpeed()), new ItemStack[] { target, item }, new ItemStack[] { book });
|
||||
|
||||
if (!InvUtils.fitAll(menu.toInventory(), recipe.getOutput(), getOutputSlots())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int inputSlot : getInputSlots()) {
|
||||
menu.consumeItem(inputSlot);
|
||||
}
|
||||
|
||||
return recipe;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isCompatible(@Nullable ItemStack item) {
|
||||
return item != null && item.getType() == Material.ENCHANTED_BOOK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getProgressBar() {
|
||||
return new ItemStack(Material.IRON_CHESTPLATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMachineIdentifier() {
|
||||
return "BOOK_BINDER";
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ParametersAreNonnullByDefault
|
||||
private Map<Enchantment, Integer> combineEnchantments(Map<Enchantment, Integer> ech1, Map<Enchantment, Integer> ech2) {
|
||||
Map<Enchantment, Integer> enchantments = new HashMap<>();
|
||||
boolean conflicts = false;
|
||||
enchantments.putAll(ech1);
|
||||
|
||||
for (Map.Entry<Enchantment, Integer> entry : ech2.entrySet()) {
|
||||
for (Map.Entry<Enchantment, Integer> conflictsWith : enchantments.entrySet()) {
|
||||
if (entry.getKey().conflictsWith(conflictsWith.getKey())) {
|
||||
conflicts = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!conflicts) {
|
||||
enchantments.merge(entry.getKey(), entry.getValue(), (a, b) -> {
|
||||
if (a.intValue() == b.intValue()) {
|
||||
if (hasCustomMaxLevel.getValue()) {
|
||||
return a + 1 > customMaxLevel.getValue() ? customMaxLevel.getValue() : a + 1;
|
||||
} else {
|
||||
return a + 1;
|
||||
}
|
||||
} else {
|
||||
int highestLevel = Math.max(a, b);
|
||||
|
||||
if (hasCustomMaxLevel.getValue()) {
|
||||
return highestLevel > customMaxLevel.getValue() ? customMaxLevel.getValue() : highestLevel;
|
||||
} else {
|
||||
return highestLevel;
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return enchantments;
|
||||
|
||||
}
|
||||
}
|
@ -1,16 +1,5 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.NotHopperable;
|
||||
@ -22,13 +11,23 @@ import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu.AdvancedMenu
|
||||
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
|
||||
import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
|
||||
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
|
||||
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
|
||||
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link ElectricSmeltery} is an electric version of the standard {@link Smeltery}.
|
||||
@ -112,12 +111,10 @@ public class ElectricSmeltery extends AContainer implements NotHopperable {
|
||||
processing.remove(b);
|
||||
return true;
|
||||
});
|
||||
|
||||
this.registerDefaultRecipes();
|
||||
}
|
||||
|
||||
private Comparator<Integer> compareSlots(DirtyChestMenu menu) {
|
||||
return (slot1, slot2) -> menu.getItemInSlot(slot1).getAmount() - menu.getItemInSlot(slot2).getAmount();
|
||||
return Comparator.comparingInt(slot -> menu.getItemInSlot(slot).getAmount());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,15 +1,5 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
|
||||
@ -22,6 +12,15 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
|
||||
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
|
||||
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class HeatedPressureChamber extends AContainer {
|
||||
|
||||
@ -73,12 +72,10 @@ public class HeatedPressureChamber extends AContainer {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.registerDefaultRecipes();
|
||||
}
|
||||
|
||||
private Comparator<Integer> compareSlots(DirtyChestMenu menu) {
|
||||
return (slot1, slot2) -> menu.getItemInSlot(slot1).getAmount() - menu.getItemInSlot(slot2).getAmount();
|
||||
return Comparator.comparingInt(slot -> menu.getItemInSlot(slot).getAmount());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3,6 +3,8 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.tools;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Effect;
|
||||
import org.bukkit.Material;
|
||||
@ -12,7 +14,6 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.BlockExplodeEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
||||
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.DamageableItem;
|
||||
@ -43,6 +44,7 @@ class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements NotPla
|
||||
private final ItemSetting<Boolean> damageOnUse = new ItemSetting<>("damage-on-use", true);
|
||||
private final ItemSetting<Boolean> callExplosionEvent = new ItemSetting<>("call-explosion-event", false);
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
public ExplosiveTool(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
|
||||
@ -59,11 +61,12 @@ class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements NotPla
|
||||
b.getWorld().playSound(b.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 0.2F, 1F);
|
||||
|
||||
List<Block> blocks = findBlocks(b);
|
||||
breakBlocks(p, tool, b, blocks, fortune, drops);
|
||||
breakBlocks(p, tool, b, blocks, drops);
|
||||
};
|
||||
}
|
||||
|
||||
private void breakBlocks(Player p, ItemStack item, Block b, List<Block> blocks, int fortune, List<ItemStack> drops) {
|
||||
@ParametersAreNonnullByDefault
|
||||
private void breakBlocks(Player p, ItemStack item, Block b, List<Block> blocks, List<ItemStack> drops) {
|
||||
if (callExplosionEvent.getValue().booleanValue()) {
|
||||
BlockExplodeEvent blockExplodeEvent = new BlockExplodeEvent(b, blocks, 0);
|
||||
Bukkit.getServer().getPluginManager().callEvent(blockExplodeEvent);
|
||||
@ -71,14 +74,14 @@ class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements NotPla
|
||||
if (!blockExplodeEvent.isCancelled()) {
|
||||
for (Block block : blockExplodeEvent.blockList()) {
|
||||
if (canBreak(p, block)) {
|
||||
breakBlock(p, item, block, fortune, drops);
|
||||
breakBlock(p, item, block, drops);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (Block block : blocks) {
|
||||
if (canBreak(p, block)) {
|
||||
breakBlock(p, item, block, fortune, drops);
|
||||
breakBlock(p, item, block, drops);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -122,7 +125,8 @@ class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements NotPla
|
||||
}
|
||||
}
|
||||
|
||||
private void breakBlock(Player p, ItemStack item, Block b, int fortune, List<ItemStack> drops) {
|
||||
@ParametersAreNonnullByDefault
|
||||
private void breakBlock(Player p, ItemStack item, Block b, List<ItemStack> drops) {
|
||||
SlimefunPlugin.getProtectionManager().logAction(p, b, ProtectableAction.BREAK_BLOCK);
|
||||
Material material = b.getType();
|
||||
|
||||
@ -135,19 +139,8 @@ class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements NotPla
|
||||
if (handler != null && !handler.onBreak(p, b, sfItem, UnregisterReason.PLAYER_BREAK)) {
|
||||
drops.add(BlockStorage.retrieve(b));
|
||||
}
|
||||
} else if (material == Material.PLAYER_HEAD || SlimefunTag.SHULKER_BOXES.isTagged(material)) {
|
||||
b.breakNaturally(item);
|
||||
} else {
|
||||
boolean applyFortune = SlimefunTag.FORTUNE_COMPATIBLE_ORES.isTagged(material);
|
||||
|
||||
for (ItemStack drop : b.getDrops(getItem())) {
|
||||
// For some reason this check is necessary with Paper
|
||||
if (drop != null && drop.getType() != Material.AIR) {
|
||||
b.getWorld().dropItemNaturally(b.getLocation(), applyFortune ? new CustomItem(drop, fortune) : drop);
|
||||
}
|
||||
}
|
||||
|
||||
b.setType(Material.AIR);
|
||||
b.breakNaturally(item);
|
||||
}
|
||||
|
||||
damageItem(p, item);
|
||||
|
@ -10,7 +10,6 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
@ -51,10 +50,7 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
|
||||
*/
|
||||
public class BlockListener implements Listener {
|
||||
|
||||
private final SlimefunPlugin plugin;
|
||||
|
||||
public BlockListener(@Nonnull SlimefunPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@ -66,23 +62,15 @@ public class BlockListener implements Listener {
|
||||
if (e.getBlockReplacedState().getType().isAir()) {
|
||||
SlimefunItem sfItem = BlockStorage.check(block);
|
||||
|
||||
if (sfItem != null) {
|
||||
/*
|
||||
* We can move the TickerTask synchronization to an async task to
|
||||
* avoid blocking the main Thread here.
|
||||
*/
|
||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||
if (!SlimefunPlugin.getTickerTask().isDeletedSoon(block.getLocation())) {
|
||||
if (sfItem != null && !SlimefunPlugin.getTickerTask().isDeletedSoon(block.getLocation())) {
|
||||
for (ItemStack item : sfItem.getDrops()) {
|
||||
if (item != null && !item.getType().isAir()) {
|
||||
SlimefunPlugin.runSync(() -> block.getWorld().dropItemNaturally(block.getLocation(), item));
|
||||
block.getWorld().dropItemNaturally(block.getLocation(), item);
|
||||
}
|
||||
}
|
||||
|
||||
BlockStorage.clearBlockInfo(block);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (BlockStorage.hasBlockInfo(e.getBlock())) {
|
||||
// If there is no air (e.g. grass) then don't let the block be placed
|
||||
e.setCancelled(true);
|
||||
@ -120,6 +108,11 @@ public class BlockListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore blocks which we have marked as deleted (Fixes #2771)
|
||||
if (SlimefunPlugin.getTickerTask().isDeletedSoon(e.getBlock().getLocation())) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack item = e.getPlayer().getInventory().getItemInMainHand();
|
||||
checkForSensitiveBlockAbove(e, item);
|
||||
|
||||
|
@ -2,15 +2,14 @@ package io.github.thebusybiscuit.slimefun4.implementation.listeners;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
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.implementation.items.cargo.CargoNode;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||
|
||||
/**
|
||||
@ -28,25 +27,15 @@ public class CargoNodeListener implements Listener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onCargoNodePlace(BlockPlaceEvent e) {
|
||||
if (e.getBlock().getY() != e.getBlockAgainst().getY() && isCargoNode(e.getItemInHand())) {
|
||||
Block b = e.getBlock();
|
||||
|
||||
if ((b.getY() != e.getBlockAgainst().getY() || !e.getBlockReplacedState().getType().isAir()) && isCargoNode(e.getItemInHand())) {
|
||||
SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "machines.CARGO_NODES.must-be-placed", true);
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCargoNode(@Nonnull ItemStack item) {
|
||||
if (SlimefunPlugin.getRegistry().isBackwardsCompatible()) {
|
||||
ItemStackWrapper wrapper = new ItemStackWrapper(item);
|
||||
|
||||
return SlimefunUtils.isItemSimilar(wrapper, SlimefunItems.CARGO_INPUT_NODE, false) || SlimefunUtils.isItemSimilar(wrapper, SlimefunItems.CARGO_OUTPUT_NODE, false) || SlimefunUtils.isItemSimilar(wrapper, SlimefunItems.CARGO_OUTPUT_NODE_2, false);
|
||||
}
|
||||
|
||||
SlimefunItem sfItem = SlimefunItem.getByItem(item);
|
||||
|
||||
if (sfItem == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return sfItem.getId().equals(SlimefunItems.CARGO_INPUT_NODE.getItemId()) || sfItem.getId().equals(SlimefunItems.CARGO_OUTPUT_NODE.getItemId()) || sfItem.getId().equals(SlimefunItems.CARGO_OUTPUT_NODE_2.getItemId());
|
||||
return SlimefunItem.getByItem(item) instanceof CargoNode;
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
||||
import org.bukkit.event.entity.EntityDeathEvent;
|
||||
import org.bukkit.event.player.PlayerExpChangeEvent;
|
||||
import org.bukkit.event.player.PlayerItemBreakEvent;
|
||||
import org.bukkit.event.player.PlayerToggleSprintEvent;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
@ -245,17 +246,26 @@ public class TalismanListener implements Listener {
|
||||
|
||||
// Wizard Talisman
|
||||
if (!enchantments.containsKey(Enchantment.SILK_TOUCH) && Enchantment.LOOT_BONUS_BLOCKS.canEnchantItem(e.getItem()) && Talisman.checkFor(e, SlimefunItems.TALISMAN_WIZARD)) {
|
||||
|
||||
for (Enchantment enchantment : enchantments.keySet()) {
|
||||
if (random.nextInt(100) < 40) {
|
||||
e.getEnchantsToAdd().put(enchantment, random.nextInt(3) + 1);
|
||||
// Randomly lower some enchantments
|
||||
for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
|
||||
if (entry.getValue() > 1 && random.nextInt(100) < 40) {
|
||||
enchantments.put(entry.getKey(), entry.getValue() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Give an extra Fortune boost (Lvl 3 - 5)
|
||||
enchantments.put(Enchantment.LOOT_BONUS_BLOCKS, random.nextInt(3) + 3);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onExperienceReceive(PlayerExpChangeEvent e) {
|
||||
if (e.getAmount() > 0 && Talisman.checkFor(e, SlimefunItems.TALISMAN_WISE)) {
|
||||
// Double-XP
|
||||
e.setAmount(e.getAmount() * 2);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onBlockDropItems(BlockDropItemEvent e) {
|
||||
// We only want to double ores
|
||||
|
@ -217,7 +217,7 @@ public final class ResearchSetup {
|
||||
register("cargo_basics", 205, "Cargo Basics", 30, SlimefunItems.CARGO_MOTOR, SlimefunItems.CARGO_MANAGER, SlimefunItems.CARGO_CONNECTOR_NODE);
|
||||
register("cargo_nodes", 206, "Cargo Setup", 30, SlimefunItems.CARGO_INPUT_NODE, SlimefunItems.CARGO_OUTPUT_NODE);
|
||||
register("electric_ingot_machines", 207, "Electric Ingot Fabrication", 18, SlimefunItems.ELECTRIC_GOLD_PAN, SlimefunItems.ELECTRIC_DUST_WASHER, SlimefunItems.ELECTRIC_INGOT_FACTORY);
|
||||
register("high_tier_electric_ingot_machines", 209, "Super Fast Ingot Fabrication", 32, SlimefunItems.ELECTRIC_GOLD_PAN_3, SlimefunItems.ELECTRIC_DUST_WASHER_3, SlimefunItems.ELECTRIC_INGOT_FACTORY_3, SlimefunItems.ELECTRIC_ORE_GRINDER_2);
|
||||
register("high_tier_electric_ingot_machines", 209, "Super Fast Ingot Fabrication", 32, SlimefunItems.ELECTRIC_GOLD_PAN_3, SlimefunItems.ELECTRIC_DUST_WASHER_3, SlimefunItems.ELECTRIC_INGOT_FACTORY_3, SlimefunItems.ELECTRIC_ORE_GRINDER_2, SlimefunItems.ELECTRIC_ORE_GRINDER_3);
|
||||
register("automated_crafting_chamber", 210, "Automated Crafting", 20, SlimefunItems.AUTOMATED_CRAFTING_CHAMBER);
|
||||
register("better_food_fabricator", 211, "Upgraded Food Fabrication", 28, SlimefunItems.FOOD_FABRICATOR_2, SlimefunItems.FOOD_COMPOSTER_2);
|
||||
register("reactor_access_port", 212, "Reactor Interaction", 18, SlimefunItems.REACTOR_ACCESS_PORT);
|
||||
@ -280,6 +280,8 @@ public final class ResearchSetup {
|
||||
register("elytra_cap", 268, "Crash Gear", 20, SlimefunItems.ELYTRA_CAP);
|
||||
register("energy_connectors", 269, "Wired Connections", 12, SlimefunItems.ENERGY_CONNECTOR);
|
||||
register("bee_armor", 270, "Bee Armor", 24, SlimefunItems.BEE_HELMET, SlimefunItems.BEE_WINGS, SlimefunItems.BEE_LEGGINGS, SlimefunItems.BEE_BOOTS);
|
||||
register("wise_talisman", 271, "Talisman of the Wise", 20, SlimefunItems.TALISMAN_WISE);
|
||||
register("book_binder", 272, "Enchantment Book Binding", 26, SlimefunItems.BOOK_BINDER);
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
|
@ -85,6 +85,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.AutoDrier;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.AutoEnchanter;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.AutomatedCraftingChamber;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.BookBinder;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.CarbonPress;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.ChargingBench;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.CropGrowthAccelerator;
|
||||
@ -861,6 +862,11 @@ public final class SlimefunItemSetup {
|
||||
false, false, "caveman", 50, new PotionEffect(PotionEffectType.FAST_DIGGING, 800, 2))
|
||||
.register(plugin);
|
||||
|
||||
new Talisman(SlimefunItems.TALISMAN_WISE,
|
||||
new ItemStack[] { SlimefunItems.MAGIC_LUMP_3, SlimefunItems.MAGICAL_GLASS, SlimefunItems.MAGIC_LUMP_3, SlimefunItems.FILLED_FLASK_OF_KNOWLEDGE, SlimefunItems.TALISMAN_MAGICIAN, SlimefunItems.FILLED_FLASK_OF_KNOWLEDGE, SlimefunItems.MAGIC_LUMP_3, SlimefunItems.MAGICAL_GLASS, SlimefunItems.MAGIC_LUMP_3},
|
||||
false, false, "wise", 20)
|
||||
.register(plugin);
|
||||
|
||||
new SlimefunItem(categories.resources, SlimefunItems.GILDED_IRON, RecipeType.SMELTERY,
|
||||
new ItemStack[] {SlimefunItems.GOLD_24K, SlimefunItems.IRON_DUST, null, null, null, null, null, null, null})
|
||||
.register(plugin);
|
||||
@ -1660,6 +1666,13 @@ public final class SlimefunItemSetup {
|
||||
.setProcessingSpeed(4)
|
||||
.register(plugin);
|
||||
|
||||
new ElectricOreGrinder(categories.electricity, SlimefunItems.ELECTRIC_ORE_GRINDER_3, RecipeType.ENHANCED_CRAFTING_TABLE,
|
||||
new ItemStack[] {SlimefunItems.REINFORCED_PLATE, SlimefunItems.HEATING_COIL, SlimefunItems.REINFORCED_PLATE, null, SlimefunItems.ELECTRIC_ORE_GRINDER_2, null, SlimefunItems.REINFORCED_PLATE, SlimefunItems.BLISTERING_INGOT_3, SlimefunItems.REINFORCED_PLATE})
|
||||
.setCapacity(1024)
|
||||
.setEnergyConsumption(45)
|
||||
.setProcessingSpeed(10)
|
||||
.register(plugin);
|
||||
|
||||
new HeatedPressureChamber(categories.electricity, SlimefunItems.HEATED_PRESSURE_CHAMBER, RecipeType.ENHANCED_CRAFTING_TABLE,
|
||||
new ItemStack[] {SlimefunItems.LEAD_INGOT, SlimefunItems.ELECTRIC_MOTOR, SlimefunItems.LEAD_INGOT, SlimefunItems.LEAD_INGOT, new ItemStack(Material.GLASS), SlimefunItems.LEAD_INGOT, SlimefunItems.LEAD_INGOT, SlimefunItems.HEATING_COIL, SlimefunItems.LEAD_INGOT})
|
||||
.setCapacity(128)
|
||||
@ -1765,6 +1778,13 @@ public final class SlimefunItemSetup {
|
||||
.setProcessingSpeed(1)
|
||||
.register(plugin);
|
||||
|
||||
new BookBinder(categories.electricity, SlimefunItems.BOOK_BINDER, RecipeType.ENHANCED_CRAFTING_TABLE,
|
||||
new ItemStack[] {null, new ItemStack(Material.ENCHANTING_TABLE), null, new ItemStack(Material.BOOKSHELF), SlimefunItems.HARDENED_METAL_INGOT, new ItemStack(Material.BOOKSHELF), SlimefunItems.SYNTHETIC_SAPPHIRE, SlimefunItems.SMALL_CAPACITOR, SlimefunItems.SYNTHETIC_SAPPHIRE})
|
||||
.setCapacity(256)
|
||||
.setEnergyConsumption(16)
|
||||
.setProcessingSpeed(1)
|
||||
.register(plugin);
|
||||
|
||||
new Multimeter(categories.technicalGadgets, SlimefunItems.MULTIMETER, RecipeType.ENHANCED_CRAFTING_TABLE,
|
||||
new ItemStack[] {SlimefunItems.COPPER_INGOT, null, SlimefunItems.COPPER_INGOT, null, SlimefunItems.REDSTONE_ALLOY, null, null, SlimefunItems.GOLD_6K, null})
|
||||
.register(plugin);
|
||||
|
@ -1,4 +1,4 @@
|
||||
package io.github.thebusybiscuit.slimefun4.core.attributes;
|
||||
package io.github.thebusybiscuit.slimefun4.utils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
@ -8,32 +8,40 @@ import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.Rechargeable;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
|
||||
/**
|
||||
* This is just a simple helper class to provide static methods to the {@link Rechargeable}
|
||||
* interface.
|
||||
*
|
||||
* @author TheBusyBiscuit
|
||||
* @author WalshyDev
|
||||
*
|
||||
* @see Rechargeable
|
||||
*
|
||||
*/
|
||||
final class RechargeableHelper {
|
||||
public final class ChargeUtils {
|
||||
|
||||
private static final String LORE_PREFIX = ChatColors.color("&8\u21E8 &e\u26A1 &7");
|
||||
private static final Pattern REGEX = Pattern.compile(ChatColors.color("(&c&o)?" + LORE_PREFIX) + "[0-9.]+ / [0-9.]+ J");
|
||||
|
||||
private RechargeableHelper() {}
|
||||
private ChargeUtils() {}
|
||||
|
||||
public static void setCharge(@Nonnull ItemMeta meta, float charge, float capacity) {
|
||||
Validate.notNull(meta, "Meta cannot be null!");
|
||||
Validate.isTrue(charge >= 0, "Charge has to be equal to or greater than 0!");
|
||||
Validate.isTrue(capacity > 0, "Capacity has to be greater than 0!");
|
||||
Validate.isTrue(charge <= capacity, "Charge may not be bigger than the capacity!");
|
||||
|
||||
static void setCharge(@Nonnull ItemMeta meta, float charge, float capacity) {
|
||||
BigDecimal decimal = BigDecimal.valueOf(charge).setScale(2, RoundingMode.HALF_UP);
|
||||
float value = decimal.floatValue();
|
||||
|
||||
@ -55,9 +63,12 @@ final class RechargeableHelper {
|
||||
meta.setLore(lore);
|
||||
}
|
||||
|
||||
static float getCharge(@Nonnull ItemMeta meta) {
|
||||
public static float getCharge(@Nonnull ItemMeta meta) {
|
||||
Validate.notNull(meta, "Meta cannot be null!");
|
||||
|
||||
NamespacedKey key = SlimefunPlugin.getRegistry().getItemChargeDataKey();
|
||||
Float value = meta.getPersistentDataContainer().get(key, PersistentDataType.FLOAT);
|
||||
PersistentDataContainer container = meta.getPersistentDataContainer();
|
||||
Float value = container.get(key, PersistentDataType.FLOAT);
|
||||
|
||||
// If persistent data is available, we just return this value
|
||||
if (value != null) {
|
||||
@ -69,12 +80,14 @@ final class RechargeableHelper {
|
||||
for (String line : meta.getLore()) {
|
||||
if (REGEX.matcher(line).matches()) {
|
||||
String data = ChatColor.stripColor(PatternUtils.SLASH_SEPARATOR.split(line)[0].replace(LORE_PREFIX, ""));
|
||||
return Float.parseFloat(data);
|
||||
|
||||
float loreValue = Float.parseFloat(data);
|
||||
container.set(key, PersistentDataType.FLOAT, loreValue);
|
||||
return loreValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
@ -53,10 +53,12 @@ public final class ItemStackWrapper extends ItemStack {
|
||||
|
||||
@Override
|
||||
public ItemMeta getItemMeta() {
|
||||
// This method normally always does a .clone() operation which can be very slow.
|
||||
// Since this class is immutable, we can simply let the super class create one copy
|
||||
// and then store that instead of creating a clone everytime.
|
||||
// This will significantly speed up any loop comparisons if used correctly.
|
||||
/*
|
||||
* This method normally always does a .clone() operation which can be very slow.
|
||||
* Since this class is immutable, we can simply let the super class create one copy
|
||||
* and then store that instead of creating a clone everytime.
|
||||
* This will significantly speed up any loop comparisons if used correctly.
|
||||
*/
|
||||
if (meta == null) {
|
||||
throw new UnsupportedOperationException("This ItemStack has no ItemMeta! Make sure to check ItemStack#hasItemMeta() before accessing this method!");
|
||||
} else {
|
||||
|
@ -0,0 +1,190 @@
|
||||
package me.mrCookieSlime.CSCoreLibPlugin.Configuration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
/**
|
||||
* An old remnant of CS-CoreLib.
|
||||
* This will be removed once we updated everything.
|
||||
* Don't look at the code, it will be gone soon, don't worry.
|
||||
*
|
||||
*/
|
||||
public class Config {
|
||||
|
||||
private final File file;
|
||||
private FileConfiguration config;
|
||||
|
||||
/**
|
||||
* Creates a new Config Object for the specified File
|
||||
*
|
||||
* @param file
|
||||
* The File for which the Config object is created for
|
||||
*/
|
||||
public Config(File file) {
|
||||
this(file, YamlConfiguration.loadConfiguration(file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Config Object for the specified File and FileConfiguration
|
||||
*
|
||||
* @param file
|
||||
* The File to save to
|
||||
* @param config
|
||||
* The FileConfiguration
|
||||
*/
|
||||
public Config(File file, FileConfiguration config) {
|
||||
this.file = file;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Config Object for the File with in
|
||||
* the specified Location
|
||||
*
|
||||
* @param path
|
||||
* The Path of the File which the Config object is created for
|
||||
*/
|
||||
public Config(String path) {
|
||||
this.file = new File(path);
|
||||
this.config = YamlConfiguration.loadConfiguration(this.file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the File the Config is handling
|
||||
*
|
||||
* @return The File this Config is handling
|
||||
*/
|
||||
public File getFile() {
|
||||
return this.file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this Config Object into a plain FileConfiguration Object
|
||||
*
|
||||
* @return The converted FileConfiguration Object
|
||||
*/
|
||||
public FileConfiguration getConfiguration() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Value for the specified Path
|
||||
*
|
||||
* @param path
|
||||
* The path in the Config File
|
||||
* @param value
|
||||
* The Value for that Path
|
||||
*/
|
||||
public void setValue(String path, Object value) {
|
||||
this.config.set(path, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the Config Object to its File
|
||||
*/
|
||||
public void save() {
|
||||
try {
|
||||
config.save(file);
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the Config Object to a File
|
||||
*
|
||||
* @param file
|
||||
* The File you are saving this Config to
|
||||
*/
|
||||
public void save(File file) {
|
||||
try {
|
||||
config.save(file);
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Value for the specified Path
|
||||
* (IF the Path does not yet exist)
|
||||
*
|
||||
* @param path
|
||||
* The path in the Config File
|
||||
* @param value
|
||||
* The Value for that Path
|
||||
*/
|
||||
public void setDefaultValue(String path, Object value) {
|
||||
if (!contains(path)) {
|
||||
setValue(path, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the Config contains the specified Path
|
||||
*
|
||||
* @param path
|
||||
* The path in the Config File
|
||||
* @return True/false
|
||||
*/
|
||||
public boolean contains(String path) {
|
||||
return config.contains(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Object at the specified Path
|
||||
*
|
||||
* @param path
|
||||
* The path in the Config File
|
||||
* @return The Value at that Path
|
||||
*/
|
||||
public Object getValue(String path) {
|
||||
return config.get(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String at the specified Path
|
||||
*
|
||||
* @param path
|
||||
* The path in the Config File
|
||||
* @return The String at that Path
|
||||
*/
|
||||
public String getString(String path) {
|
||||
return config.getString(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recreates the File of this Config
|
||||
*/
|
||||
public void createFile() {
|
||||
try {
|
||||
this.file.createNewFile();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all Paths in this Config
|
||||
*
|
||||
* @return All Paths in this Config
|
||||
*/
|
||||
public Set<String> getKeys() {
|
||||
return config.getKeys(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all Sub-Paths in this Config
|
||||
*
|
||||
* @param path
|
||||
* The path in the Config File
|
||||
* @return All Sub-Paths of the specified Path
|
||||
*/
|
||||
public Set<String> getKeys(String path) {
|
||||
return config.getConfigurationSection(path).getKeys(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the Configuration File
|
||||
*/
|
||||
public void reload() {
|
||||
this.config = YamlConfiguration.loadConfiguration(this.file);
|
||||
}
|
||||
}
|
@ -0,0 +1,344 @@
|
||||
package me.mrCookieSlime.CSCoreLibPlugin.general.Inventory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
/**
|
||||
* An old remnant of CS-CoreLib.
|
||||
* This will be removed once we updated everything.
|
||||
* Don't look at the code, it will be gone soon, don't worry.
|
||||
*
|
||||
*/
|
||||
public class ChestMenu {
|
||||
|
||||
private boolean clickable;
|
||||
private boolean emptyClickable;
|
||||
private String title;
|
||||
private Inventory inv;
|
||||
private List<ItemStack> items;
|
||||
private Map<Integer, MenuClickHandler> handlers;
|
||||
private MenuOpeningHandler open;
|
||||
private MenuCloseHandler close;
|
||||
private MenuClickHandler playerclick;
|
||||
|
||||
/**
|
||||
* Creates a new ChestMenu with the specified
|
||||
* Title
|
||||
*
|
||||
* @param title
|
||||
* The title of the Menu
|
||||
*/
|
||||
public ChestMenu(String title) {
|
||||
this.title = ChatColor.translateAlternateColorCodes('&', title);
|
||||
this.clickable = false;
|
||||
this.emptyClickable = true;
|
||||
this.items = new ArrayList<>();
|
||||
this.handlers = new HashMap<>();
|
||||
|
||||
this.open = p -> {};
|
||||
this.close = p -> {};
|
||||
this.playerclick = (p, slot, item, action) -> isPlayerInventoryClickable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles whether Players can access there
|
||||
* Inventory while viewing this Menu
|
||||
*
|
||||
* @param clickable
|
||||
* Whether the Player can access his Inventory
|
||||
* @return The ChestMenu Instance
|
||||
*/
|
||||
public ChestMenu setPlayerInventoryClickable(boolean clickable) {
|
||||
this.clickable = clickable;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the Player's Inventory is
|
||||
* accessible while viewing this Menu
|
||||
*
|
||||
* @return Whether the Player Inventory is clickable
|
||||
*/
|
||||
public boolean isPlayerInventoryClickable() {
|
||||
return clickable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles whether Players can click the
|
||||
* empty menu slots while viewing this Menu
|
||||
*
|
||||
* @param emptyClickable
|
||||
* Whether the Player can click empty slots
|
||||
* @return The ChestMenu Instance
|
||||
*/
|
||||
public ChestMenu setEmptySlotsClickable(boolean emptyClickable) {
|
||||
this.emptyClickable = emptyClickable;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the empty menu slots are
|
||||
* clickable while viewing this Menu
|
||||
*
|
||||
* @return Whether the empty menu slots are clickable
|
||||
*/
|
||||
public boolean isEmptySlotsClickable() {
|
||||
return emptyClickable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a ClickHandler to ALL Slots of the
|
||||
* Player's Inventory
|
||||
*
|
||||
* @param handler
|
||||
* The MenuClickHandler
|
||||
* @return The ChestMenu Instance
|
||||
*/
|
||||
public ChestMenu addPlayerInventoryClickHandler(MenuClickHandler handler) {
|
||||
this.playerclick = handler;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an Item to the Inventory in that Slot
|
||||
*
|
||||
* @param slot
|
||||
* The Slot in the Inventory
|
||||
* @param item
|
||||
* The Item for that Slot
|
||||
* @return The ChestMenu Instance
|
||||
*/
|
||||
public ChestMenu addItem(int slot, ItemStack item) {
|
||||
final int size = this.items.size();
|
||||
if (size > slot)
|
||||
this.items.set(slot, item);
|
||||
else {
|
||||
for (int i = 0; i < slot - size; i++) {
|
||||
this.items.add(null);
|
||||
}
|
||||
this.items.add(item);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an Item to the Inventory in that Slot
|
||||
* as well as a Click Handler
|
||||
*
|
||||
* @param slot
|
||||
* The Slot in the Inventory
|
||||
* @param item
|
||||
* The Item for that Slot
|
||||
* @param clickHandler
|
||||
* The MenuClickHandler for that Slot
|
||||
* @return The ChestMenu Instance
|
||||
*/
|
||||
public ChestMenu addItem(int slot, ItemStack item, MenuClickHandler clickHandler) {
|
||||
addItem(slot, item);
|
||||
addMenuClickHandler(slot, clickHandler);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ItemStack in that Slot
|
||||
*
|
||||
* @param slot
|
||||
* The Slot in the Inventory
|
||||
* @return The ItemStack in that Slot
|
||||
*/
|
||||
public ItemStack getItemInSlot(int slot) {
|
||||
setup();
|
||||
return this.inv.getItem(slot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a certain Action upon clicking an
|
||||
* Item in the Menu
|
||||
*
|
||||
* @param slot
|
||||
* The Slot in the Inventory
|
||||
* @param handler
|
||||
* The MenuClickHandler
|
||||
* @return The ChestMenu Instance
|
||||
*/
|
||||
public ChestMenu addMenuClickHandler(int slot, MenuClickHandler handler) {
|
||||
this.handlers.put(slot, handler);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a certain Action upon opening
|
||||
* this Menu
|
||||
*
|
||||
* @param handler
|
||||
* The MenuOpeningHandler
|
||||
* @return The ChestMenu Instance
|
||||
*/
|
||||
public ChestMenu addMenuOpeningHandler(MenuOpeningHandler handler) {
|
||||
this.open = handler;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a certain Action upon closing
|
||||
* this Menu
|
||||
*
|
||||
* @param handler
|
||||
* The MenuCloseHandler
|
||||
* @return The ChestMenu Instance
|
||||
*/
|
||||
public ChestMenu addMenuCloseHandler(MenuCloseHandler handler) {
|
||||
this.close = handler;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the Creation of the Menu
|
||||
*
|
||||
* @return The ChestMenu Instance
|
||||
*/
|
||||
@Deprecated
|
||||
public ChestMenu build() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Array containing the Contents
|
||||
* of this Inventory
|
||||
*
|
||||
* @return The Contents of this Inventory
|
||||
*/
|
||||
public ItemStack[] getContents() {
|
||||
setup();
|
||||
return this.inv.getContents();
|
||||
}
|
||||
|
||||
private void setup() {
|
||||
if (this.inv != null)
|
||||
return;
|
||||
this.inv = Bukkit.createInventory(null, ((int) Math.ceil(this.items.size() / 9F)) * 9, title);
|
||||
for (int i = 0; i < this.items.size(); i++) {
|
||||
this.inv.setItem(i, this.items.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
public void reset(boolean update) {
|
||||
if (update)
|
||||
this.inv.clear();
|
||||
else
|
||||
this.inv = Bukkit.createInventory(null, ((int) Math.ceil(this.items.size() / 9F)) * 9, title);
|
||||
for (int i = 0; i < this.items.size(); i++) {
|
||||
this.inv.setItem(i, this.items.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies an ItemStack in an ALREADY OPENED ChestMenu
|
||||
*
|
||||
* @param slot
|
||||
* The Slot of the Item which will be replaced
|
||||
* @param item
|
||||
* The new Item
|
||||
*/
|
||||
public void replaceExistingItem(int slot, ItemStack item) {
|
||||
setup();
|
||||
this.inv.setItem(slot, item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens this Menu for the specified Player/s
|
||||
*
|
||||
* @param players
|
||||
* The Players who will see this Menu
|
||||
*/
|
||||
public void open(Player... players) {
|
||||
setup();
|
||||
for (Player p : players) {
|
||||
p.openInventory(this.inv);
|
||||
MenuListener.menus.put(p.getUniqueId(), this);
|
||||
if (open != null)
|
||||
open.onOpen(p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the MenuClickHandler which was registered for the specified Slot
|
||||
*
|
||||
* @param slot
|
||||
* The Slot in the Inventory
|
||||
* @return The MenuClickHandler registered for the specified Slot
|
||||
*/
|
||||
public MenuClickHandler getMenuClickHandler(int slot) {
|
||||
return handlers.get(slot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the registered MenuCloseHandler
|
||||
*
|
||||
* @return The registered MenuCloseHandler
|
||||
*/
|
||||
public MenuCloseHandler getMenuCloseHandler() {
|
||||
return close;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the registered MenuOpeningHandler
|
||||
*
|
||||
* @return The registered MenuOpeningHandler
|
||||
*/
|
||||
public MenuOpeningHandler getMenuOpeningHandler() {
|
||||
return open;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the registered MenuClickHandler
|
||||
* for Player Inventories
|
||||
*
|
||||
* @return The registered MenuClickHandler
|
||||
*/
|
||||
public MenuClickHandler getPlayerInventoryClickHandler() {
|
||||
return playerclick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this ChestMenu Instance into a
|
||||
* normal Inventory
|
||||
*
|
||||
* @return The converted Inventory
|
||||
*/
|
||||
public Inventory toInventory() {
|
||||
return this.inv;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface MenuClickHandler {
|
||||
|
||||
public boolean onClick(Player p, int slot, ItemStack item, ClickAction action);
|
||||
}
|
||||
|
||||
public interface AdvancedMenuClickHandler extends MenuClickHandler {
|
||||
|
||||
public boolean onClick(InventoryClickEvent e, Player p, int slot, ItemStack cursor, ClickAction action);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface MenuOpeningHandler {
|
||||
|
||||
public void onOpen(Player p);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface MenuCloseHandler {
|
||||
|
||||
public void onClose(Player p);
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package me.mrCookieSlime.CSCoreLibPlugin.general.Inventory;
|
||||
|
||||
/**
|
||||
* An old remnant of CS-CoreLib.
|
||||
* This will be removed once we updated everything.
|
||||
* Don't look at the code, it will be gone soon, don't worry.
|
||||
*
|
||||
*/
|
||||
public class ClickAction {
|
||||
|
||||
private boolean right;
|
||||
private boolean shift;
|
||||
|
||||
public ClickAction(boolean rightClicked, boolean shiftClicked) {
|
||||
this.right = rightClicked;
|
||||
this.shift = shiftClicked;
|
||||
}
|
||||
|
||||
public boolean isRightClicked() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public boolean isShiftClicked() {
|
||||
return shift;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
package me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.Item;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
/**
|
||||
* An old remnant of CS-CoreLib.
|
||||
* This will be removed once we updated everything.
|
||||
* Don't look at the code, it will be gone soon, don't worry.
|
||||
*
|
||||
* @deprecated This was a horrible idea. Don't use it.
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public class CustomItemSerializer {
|
||||
|
||||
public enum ItemFlag {
|
||||
|
||||
MATERIAL(0),
|
||||
DATA(1),
|
||||
AMOUNT(2),
|
||||
DURABILITY(3),
|
||||
ENCHANTMENTS(4),
|
||||
ITEMMETA_DISPLAY_NAME(5),
|
||||
ITEMMETA_LORE(6);
|
||||
|
||||
private int weight;
|
||||
|
||||
ItemFlag(int weight) {
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
public int getWeight() {
|
||||
return this.weight;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static ItemFlagComparator comparator = new ItemFlagComparator();
|
||||
|
||||
public static String serialize(ItemStack item, ItemFlag... flags) {
|
||||
if (item == null)
|
||||
return "NULL";
|
||||
List<ItemFlag> flaglist = Arrays.asList(flags);
|
||||
|
||||
Collections.sort(flaglist, comparator);
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
int i = 0;
|
||||
for (ItemFlag flag : flags) {
|
||||
if (i > 0)
|
||||
builder.append(" </sep> ");
|
||||
builder.append(flag.toString() + "=");
|
||||
|
||||
switch (flag) {
|
||||
case AMOUNT: {
|
||||
builder.append(item.getAmount());
|
||||
break;
|
||||
}
|
||||
case DATA: {
|
||||
builder.append((int) item.getData().getData());
|
||||
break;
|
||||
}
|
||||
case DURABILITY: {
|
||||
builder.append((int) item.getDurability());
|
||||
break;
|
||||
}
|
||||
case ENCHANTMENTS:
|
||||
for (Enchantment enchantment : Enchantment.values()) {
|
||||
if (item.getEnchantments().containsKey(enchantment)) {
|
||||
builder.append(enchantment.getName() + ":" + item.getEnchantmentLevel(enchantment));
|
||||
} else {
|
||||
builder.append(enchantment.getName() + ":0");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ITEMMETA_DISPLAY_NAME: {
|
||||
if (item.hasItemMeta() && item.getItemMeta().hasDisplayName()) {
|
||||
builder.append(item.getItemMeta().getDisplayName().replaceAll("\\u00a7", "&"));
|
||||
} else {
|
||||
builder.append("NONE");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ITEMMETA_LORE: {
|
||||
if (item.hasItemMeta() && item.getItemMeta().hasLore()) {
|
||||
builder.append(item.getItemMeta().getLore().toString().replaceAll("\\u00a7", "&"));
|
||||
} else {
|
||||
builder.append("NONE");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MATERIAL: {
|
||||
builder.append(item.getType().toString());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static boolean equals(ItemStack stack1, ItemStack stack2, ItemFlag... flags) {
|
||||
return serialize(stack1, flags).equals(serialize(stack2, flags));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.Item;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.Item.CustomItemSerializer.ItemFlag;
|
||||
|
||||
/**
|
||||
* An old remnant of CS-CoreLib.
|
||||
* This will be removed once we updated everything.
|
||||
* Don't look at the code, it will be gone soon, don't worry.
|
||||
*
|
||||
* @deprecated This was a horrible idea. Don't use it.
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public class ItemFlagComparator implements Comparator<ItemFlag> {
|
||||
|
||||
@Override
|
||||
public int compare(ItemFlag flag1, ItemFlag flag2) {
|
||||
return flag1.getWeight() - flag2.getWeight();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package me.mrCookieSlime.CSCoreLibPlugin.general.Inventory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu.AdvancedMenuClickHandler;
|
||||
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu.MenuClickHandler;
|
||||
|
||||
/**
|
||||
* An old {@link Listener} for CS-CoreLib
|
||||
*
|
||||
* @deprecated This is an old remnant of CS-CoreLib, the last bits of the past. They will be removed once everything is
|
||||
* updated.
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public class MenuListener implements Listener {
|
||||
|
||||
static final Map<UUID, ChestMenu> menus = new HashMap<>();
|
||||
|
||||
public MenuListener(Plugin plugin) {
|
||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onClose(InventoryCloseEvent e) {
|
||||
ChestMenu menu = menus.remove(e.getPlayer().getUniqueId());
|
||||
|
||||
if (menu != null) {
|
||||
menu.getMenuCloseHandler().onClose((Player) e.getPlayer());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onClick(InventoryClickEvent e) {
|
||||
ChestMenu menu = menus.get(e.getWhoClicked().getUniqueId());
|
||||
|
||||
if (menu != null) {
|
||||
if (e.getRawSlot() < e.getInventory().getSize()) {
|
||||
MenuClickHandler handler = menu.getMenuClickHandler(e.getSlot());
|
||||
|
||||
if (handler == null) {
|
||||
e.setCancelled(!menu.isEmptySlotsClickable() && (e.getCurrentItem() == null || e.getCurrentItem().getType() == Material.AIR));
|
||||
} else if (handler instanceof AdvancedMenuClickHandler) {
|
||||
e.setCancelled(!((AdvancedMenuClickHandler) handler).onClick(e, (Player) e.getWhoClicked(), e.getSlot(), e.getCursor(), new ClickAction(e.isRightClick(), e.isShiftClick())));
|
||||
} else {
|
||||
e.setCancelled(!handler.onClick((Player) e.getWhoClicked(), e.getSlot(), e.getCurrentItem(), new ClickAction(e.isRightClick(), e.isShiftClick())));
|
||||
}
|
||||
} else {
|
||||
e.setCancelled(!menu.getPlayerInventoryClickHandler().onClick((Player) e.getWhoClicked(), e.getSlot(), e.getCurrentItem(), new ClickAction(e.isRightClick(), e.isShiftClick())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Old CS-CoreLib 1.X code.
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
package me.mrCookieSlime.CSCoreLibPlugin;
|
@ -74,8 +74,6 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock,
|
||||
processing.remove(b);
|
||||
return true;
|
||||
});
|
||||
|
||||
registerDefaultRecipes();
|
||||
}
|
||||
|
||||
@ParametersAreNonnullByDefault
|
||||
@ -239,6 +237,8 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock,
|
||||
warn("Make sure to call '" + getClass().getSimpleName() + "#setProcessingSpeed(...)' before registering!");
|
||||
}
|
||||
|
||||
registerDefaultRecipes();
|
||||
|
||||
if (getCapacity() > 0 && getEnergyConsumption() > 0 && getSpeed() > 0) {
|
||||
super.register(addon);
|
||||
}
|
||||
|
@ -2,10 +2,11 @@ package me.mrCookieSlime.Slimefun.api;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
@ -39,12 +40,13 @@ public class BlockInfoConfig extends Config {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Map<String, String> getMap() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void store(String path, Object value) {
|
||||
public void setValue(String path, Object value) {
|
||||
if (value != null && !(value instanceof String)) {
|
||||
throw new UnsupportedOperationException("Can't set \"" + path + "\" to \"" + value + "\" (type: " + value.getClass().getSimpleName() + ") because BlockInfoConfig only supports Strings");
|
||||
}
|
||||
@ -76,70 +78,42 @@ public class BlockInfoConfig extends Config {
|
||||
return data.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(String path) {
|
||||
throw invalidType(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String path) {
|
||||
throw invalidType(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStringList(String path) {
|
||||
throw invalidType(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> getIntList(String path) {
|
||||
throw invalidType(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getDouble(String path) {
|
||||
throw invalidType(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getKeys(String path) {
|
||||
throw invalidType(path);
|
||||
}
|
||||
|
||||
private UnsupportedOperationException invalidType(String path) {
|
||||
return new UnsupportedOperationException("Can't get \"" + path + "\" because BlockInfoConfig only supports String values");
|
||||
throw new UnsupportedOperationException("Cannot get keys for BlockInfoConfig");
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getFile() {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException("BlockInfoConfigs do not have a File");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileConfiguration getConfiguration() {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException("BlockInfoConfigs do not have a FileConfiguration");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException("BlockInfoConfigs cannot be saved to a File");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(File file) {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException("BlockInfoConfigs cannot be saved to a File");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createFile() {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException("BlockInfoConfigs cannot be created from a File");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException("BlockInfoConfigs cannot be reloaded");
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String toJSON() {
|
||||
return new GsonBuilder().create().toJson(data);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
@ -27,6 +28,8 @@ import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
@ -360,6 +363,36 @@ public class BlockStorage {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will return an {@link ImmutableMap} of the underline {@code Map<String, Config>} of
|
||||
* this worlds {@link BlockStorage}.
|
||||
*
|
||||
* @return An {@link ImmutableMap} of the raw data.
|
||||
*/
|
||||
@Nonnull
|
||||
public Map<Location, Config> getRawStorage() {
|
||||
return ImmutableMap.copyOf(this.storage);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will return an {@link ImmutableMap} of the underline {@code Map<String, Config>} of
|
||||
* this worlds {@link BlockStorage}. If there is no registered world then this will return null.
|
||||
*
|
||||
* @param world The world of which to fetch the data from.
|
||||
* @return An {@link ImmutableMap} of the raw data or null if the world isn't registered.
|
||||
*/
|
||||
@Nullable
|
||||
public static Map<Location, Config> getRawStorage(@Nonnull World world) {
|
||||
Validate.notNull(world, "World cannot be null!");
|
||||
|
||||
BlockStorage storage = getStorage(world);
|
||||
if (storage != null) {
|
||||
return storage.getRawStorage();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void store(Block block, ItemStack item) {
|
||||
SlimefunItem sfitem = SlimefunItem.getByItem(item);
|
||||
|
||||
|
@ -17,7 +17,7 @@ class EmptyBlockData extends BlockInfoConfig {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void store(String path, Object value) {
|
||||
public void setValue(String path, Object value) {
|
||||
throw new UnsupportedOperationException("Cannot store values (" + path + ':' + value + " on a read-only data object!");
|
||||
}
|
||||
|
||||
|
@ -105,18 +105,21 @@ public class DirtyChestMenu extends ChestMenu {
|
||||
if (stack == null) {
|
||||
replaceExistingItem(slot, item);
|
||||
return null;
|
||||
} else if (stack.getAmount() < stack.getMaxStackSize()) {
|
||||
} else {
|
||||
int maxStackSize = Math.min(stack.getMaxStackSize(), toInventory().getMaxStackSize());
|
||||
if (stack.getAmount() < maxStackSize) {
|
||||
if (wrapper == null) {
|
||||
wrapper = new ItemStackWrapper(item);
|
||||
}
|
||||
|
||||
if (ItemUtils.canStack(wrapper, stack)) {
|
||||
amount -= (stack.getMaxStackSize() - stack.getAmount());
|
||||
stack.setAmount(Math.min(stack.getAmount() + item.getAmount(), stack.getMaxStackSize()));
|
||||
amount -= (maxStackSize - stack.getAmount());
|
||||
stack.setAmount(Math.min(stack.getAmount() + item.getAmount(), maxStackSize));
|
||||
item.setAmount(amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (amount > 0) {
|
||||
return new CustomItem(item, amount);
|
||||
|
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Old Slimefun 4.0 code.
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
package me.mrCookieSlime.Slimefun;
|
7
src/main/java/me/mrCookieSlime/package-info.java
Normal file
7
src/main/java/me/mrCookieSlime/package-info.java
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* These are the old packages, the remnants of past versions that have not been rewritten yet.
|
||||
* Don't look too close at the code that lays here. It's horrible, believe me.
|
||||
* Once we updated everything, all of these classes will be removed.
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
package me.mrCookieSlime;
|
@ -134,6 +134,7 @@ messages:
|
||||
wizard: "&a&oВашия Талисман Ви даде по-добро Ниво Fortune, но може да е намалило
|
||||
Нивата на някои от другите Ви Enchantment-и"
|
||||
caveman: "&a&oВашия Талисман Ви дава haste или познато, като бързо чупене"
|
||||
wise: "&a&oВашия Талисман удвой вашите XP дропове"
|
||||
soulbound-rune:
|
||||
fail: "& cМожете да свържете само един елемент с душата си наведнъж."
|
||||
success: "&aВие успешно свързахте този предмет с душата си! Когато умрете Вие
|
||||
|
@ -136,6 +136,7 @@ messages:
|
||||
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"
|
||||
wise: "&a&oDein Talisman hat soeben deine Erfahrungspunkte verdoppelt"
|
||||
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
|
||||
@ -319,6 +320,7 @@ android:
|
||||
own: "&4Du kannst nicht dein eigenes Skript bewerten!"
|
||||
already: "&4Du hast dieses Skript bereits bewertet!"
|
||||
editor: Skripteditor
|
||||
too-long: "&cDieses Skript ist zu lang, um es zu bearbeiten!"
|
||||
languages:
|
||||
default: Server-Standard
|
||||
en: Englisch
|
||||
|
@ -158,6 +158,7 @@ messages:
|
||||
whirlwind: '&a&oYour Talisman reflected the Projectile'
|
||||
wizard: '&a&oYour Talisman has given you a better Fortune Level but maybe also lowered some other Enchantment Levels'
|
||||
caveman: '&a&oYour Talisman gave you haste'
|
||||
wise: '&a&oYour Talisman has doubled your experience drops'
|
||||
|
||||
soulbound-rune:
|
||||
fail: '&cYou can only bind one item to your soul at a time.'
|
||||
|
@ -25,9 +25,9 @@ commands:
|
||||
not-rechargeable: Este ítem no puede ser cargado!
|
||||
timings:
|
||||
description: Timings para Slimefun y sus addon
|
||||
please-wait: "&ePor favor, espere un segundo... ¡Los resultados están llegando!"
|
||||
verbose-player: "&4La flag verbose no puede ser usada por un jugador!"
|
||||
unknown-flag: "&4flag desconocida: &c%flag%"
|
||||
please-wait: "&ePor favor, espere un segundo... ¡Los resultados están llegando!"
|
||||
guide:
|
||||
search:
|
||||
message: "&b¿Qué te gustaría buscar?"
|
||||
@ -134,6 +134,7 @@ messages:
|
||||
wizard: "&a&oTu talismán te ha dado un mayor nivel de fortuna, pero pudo disminuír
|
||||
el nivel de otros encantamientos."
|
||||
caveman: "&a&oTu Talismán te ha dado Haste"
|
||||
wise: "&a&oTu Talismán ha duplicado tu drop de experiencia"
|
||||
soulbound-rune:
|
||||
fail: "&cSolo puedes ligar un objeto a tu alma."
|
||||
success: "&a¡Has ligado este objeto a tu alma exitosamente! No lo perderás al
|
||||
@ -189,9 +190,9 @@ messages:
|
||||
invalid-item: "&c¡&4%item% &cno es un objeto válido!"
|
||||
invalid-amount: "&c¡&4%amount% &cno es un valor válido: tiene que ser mayor a 0!"
|
||||
invalid-research: "&c¡&4%research% &cno es un conocimiento válido!"
|
||||
mode-change: 'El modo de &b%device% ha cambiado a: &9%mode%'
|
||||
bee-suit-slow-fall: "&eTus alas de Abeja te ayudarán a llegar seguro y lento al
|
||||
piso"
|
||||
mode-change: 'El modo de &b%device% ha cambiado a: &9%mode%'
|
||||
machines:
|
||||
pattern-not-found: "&eLo siento, no puedo reconocer esta receta. Por favor coloca
|
||||
el objeto en el patrón correcto dentro del dispensador."
|
||||
@ -314,6 +315,7 @@ android:
|
||||
own: "&4¡No puedes calificar tu propio script!"
|
||||
already: "&4¡Ya has calificado este script!"
|
||||
editor: Editor de Guión
|
||||
too-long: "&cEl script es demasiado largo para editar!"
|
||||
languages:
|
||||
default: Predeterminado
|
||||
en: Inglés
|
||||
@ -335,6 +337,7 @@ languages:
|
||||
zh-CN: Chino (China)
|
||||
el: Griego
|
||||
he: Hebreo
|
||||
pt: Portugués (Portugal)
|
||||
ar: Árabe
|
||||
af: Africano
|
||||
da: Danés
|
||||
@ -346,7 +349,6 @@ languages:
|
||||
fa: Persa
|
||||
th: Tailandés
|
||||
ro: Rumano
|
||||
pt: Portugués (Portugal)
|
||||
pt-BR: Portugués (Brasil)
|
||||
bg: Búlgaro
|
||||
ko: Coreano
|
||||
|
359
src/main/resources/languages/messages_he.yml
Normal file
359
src/main/resources/languages/messages_he.yml
Normal file
@ -0,0 +1,359 @@
|
||||
---
|
||||
commands:
|
||||
help: הצגת מסך עזרה
|
||||
teleporter: ראה נקודות ציון של שחקנים אחרים
|
||||
search: חפש במדריך את המונח הנתון
|
||||
cheat: מאפשר לזמן פריטים ברמאות
|
||||
give: נותן למישהו פירטי סליים פאן
|
||||
guide: תן לעצמך מדריך סליים פאן
|
||||
backpack:
|
||||
description: אחזר עותק של גיבוי קיים
|
||||
invalid-id: " המספר המזהה חייב להיות מספר לא שלילי!&4"
|
||||
player-never-joined: "&4!שום שחקן בשם זה לא נמצא"
|
||||
backpack-does-not-exist: "&4!הגיבוי שצוין אינו קיים"
|
||||
restored-backpack-given: "&a!הגיבוי שוחזר ונוסף למלאי"
|
||||
charge:
|
||||
description: טוען את הפריט שאתה מחזיק
|
||||
charge-success: "!הפריט נטען"
|
||||
not-rechargeable: הפריט הזה לא יכול להטען!
|
||||
timings:
|
||||
description: תזמונים עבור סליים פאן והתוסף שלה
|
||||
please-wait: "&e !אנא המתן שנייה ... התוצאות מגיעות"
|
||||
verbose-player: "&4 האיתות המילולי אינו יכול להיות בשימוש על ידי שחקן!"
|
||||
unknown-flag: "&4איתות לא ידוע: &c%flag%"
|
||||
versions: הצגת תוספים מותקנים
|
||||
open_guide: פתח את המדריך בלי להשתמש בספר
|
||||
stats: מציג כמה נתונים סטטיסטיים על שחקן
|
||||
research:
|
||||
description: 'בטל נעילה /מחקרים עבור שחקן זה '
|
||||
reset: "&c איפס את הידע של %שחקן% זה"
|
||||
reset-target: "&cהידע שלך אופס "
|
||||
guide:
|
||||
title:
|
||||
main: סליים פאן מדריך
|
||||
credits: סליים פאן4 תורמים
|
||||
wiki: סליים פאן4 ויקי
|
||||
addons: 'תוספות לסליים פאן '
|
||||
versions: גרסאות מותקנות
|
||||
settings: 'הגדרות & מידע '
|
||||
languages: בחר את השפה המועדפת עליך
|
||||
bugs: דיווחי שגיאות
|
||||
source: קוד מקור
|
||||
back:
|
||||
guide: חזור למדריך סליים פאן
|
||||
title: חזור
|
||||
settings: חזור ללוח ההגדרות
|
||||
tooltips:
|
||||
wiki: ראה פריט זה באתר הרשימי של סליים פאן ויקי
|
||||
recipes:
|
||||
climbing-pick: משטחים שאפשר לטפס עליהם
|
||||
machine: מתכונים שנעשו במכונה זו
|
||||
miner: משאבים שתוכלו להשיג אצל כורה זה
|
||||
generator: סוגי דלק זמינים
|
||||
gold-pan: משאבים שתוכלו להשיג
|
||||
open-category: לחץ לפתיחה
|
||||
versions-notice: אלה חשובים מאוד כשמדווחים על באגים!
|
||||
work-in-progress: תכונה זו עדיין לא הושלמה במלואה!
|
||||
languages:
|
||||
change: לחץ כדי לבחור שפה חדשה
|
||||
description:
|
||||
- "&7כעת יש לך אפשרות לשנות"
|
||||
- "&7השפה שבה סליים פאן"
|
||||
- "&7יוצג בפניך. פריטים"
|
||||
- "&7לא ניתן לתרגם לעת עתה."
|
||||
updated: "&a :השפה שלך הוגדרה בהצלחה ל &b%lang%"
|
||||
translations:
|
||||
name: "&aIs משהו חסר?"
|
||||
lore: לחץ כדי להוסיף תרגום משלך
|
||||
select: 'לחץ כדי לבחור שפה זאת '
|
||||
select-default: לחץ לבחירת שפת ברירת המחדל
|
||||
selected-language: 'נבחר כעת:'
|
||||
credits:
|
||||
open: לחץ כדי לראות את התורמים שלנו
|
||||
description:
|
||||
- "&7 סליים פאן הוא פרויקט קוד פתוח "
|
||||
- "&7ומתוחזק על ידי קהילה גדולה של אנשים."
|
||||
- "&7על &e%contributors% &7אנשים עבדו"
|
||||
- "&7.סליים פאן לאורך כל השנים האלה "
|
||||
commit: להתחייב
|
||||
commits: מתחייב
|
||||
roles:
|
||||
developer: "&6 מפתח"
|
||||
wiki: "&3ויקי עורך "
|
||||
resourcepack: "&c אמן חבילת משאבים"
|
||||
translator: "&9מתרגם"
|
||||
profile-link: "לחץ כדי לבקר את הפרופיל שלהם \nב -GitHub"
|
||||
search:
|
||||
message: &b מה תרצה לחפש?
|
||||
name: "&7חפש...."
|
||||
tooltip: "&b לחץ לחפש פריט"
|
||||
inventory: "%item% מחפש עבור: "
|
||||
cheat:
|
||||
no-multiblocks: "&4 אתה לא יכול לרמות בריבוי מבנים אתה חייב לבנות אותם!"
|
||||
pages:
|
||||
previous: עמוד קודם
|
||||
next: עמוד הבא
|
||||
locked: נעול
|
||||
locked-category:
|
||||
- כדי לבטל את הנעילה של קטגוריה זו
|
||||
- 'צריך לפתוח את כל הפריטים מה '
|
||||
- הקטגוריות הבאות
|
||||
messages:
|
||||
not-enough-xp: "&4אין לך מספיק נקודות ניסיון\nכדי לפתוח את זה "
|
||||
talisman:
|
||||
angel: "&a&o הקמע שלך הציל אותך מלקבל נזק נפילה"
|
||||
fire: "&a&oהקמע שלך הציל אותך מלהישרף למוות"
|
||||
caveman: "&a&oהקמע שלך נתן לך מהירות"
|
||||
anvil: "&a&o הקמע שלך הציל את הכלי שלך מלהישבר"
|
||||
miner: "&a&o הקמע שלך בכפיל את הפריטים הנופלים"
|
||||
hunter: "&a&o הקמע שלך בכפיל את הפריטים הנופלים"
|
||||
lava: "&a&oהקמע שלך הציל אותך מלהישרף למוות"
|
||||
water: "&a&oהקמע שלך הציל אותך מלטבוע "
|
||||
magician: "&a%o הקמע שלך העניק לך כישוף נוסף"
|
||||
traveller: "&a&o הקמע שלך נתן לך דחיפת מהירות"
|
||||
warrior: "&a&oהקמע שלך שיפר את כוחך לזמן מה"
|
||||
knight: "&a&o הקמע שלך נתן לך 5 שניות ריפוי"
|
||||
whirlwind: "&a&o הקמע שלך שיקף את הטיל"
|
||||
wizard: "&a&o הקמע שלך העניק לך רמת הון טובה יותר אבל אולי גם הוריד כמה רמות הקסם
|
||||
אחרות"
|
||||
fortune-cookie:
|
||||
- "&7 עזור לי, אני כלוא במפעל לעוגיות "
|
||||
- "&7אתה תמות מחר על ידי.... קריפר "
|
||||
- "&7 בשלב מסוים בחיים שלך משהו רע יקרה!!!"
|
||||
- "&7בשבוע הבא תבחין שזה לא העולם האמיתי, אתה נמצא במשחק מחשב"
|
||||
- "עוגיה זו תהיה טעימה תוך כמה שניות &7"
|
||||
- '&7 המילה האחרונה שתשמע תהיה "להשמיד !!!"'
|
||||
- "&7מה שלא תעשה אל תחבק קריפר ניסיתי. זה מרגיש טוב,אבל לא שווה את זה"
|
||||
- "&7התשובה היא 42"
|
||||
- "&7 וולשי ביום ירחיקו את הצרות."
|
||||
- "&7 לעולם אל תחפור ישר למטה!"
|
||||
- "&7זו רק שריטה!"
|
||||
- "&7תמיד תסתכל על הצד הטוב שבחיים"
|
||||
- "&7זה היה למעשה ביסקוויט ולא עוגיה"
|
||||
- "&7שלטי הניאון דולקים"
|
||||
piglin-barter: &4 אתה לא יכול לסחור עם חזירונים באמצעות חפצי סליים פאן
|
||||
enchantment-rune:
|
||||
fail: "&cאת לא יכול להחליף עם חזירונים חפצים של סליים פאן."
|
||||
no-enchantment: "&cלא נמצא שום קסם ישים לפריט הזה."
|
||||
success: "&aהחלת בהצלחה קסם אקראי החל על פריט זה."
|
||||
tape-measure:
|
||||
no-anchor: "&c אתה צריך להגדיר עוגן לפני שתוכל להתחיל למדוד!"
|
||||
wrong-world: "!&cנראה שהעוגן שלך נמצא בעולם אחר"
|
||||
distance: "&7המדידה נלקחה &eDistance: %distance%."
|
||||
anchor-set: "&aהעוגן הוגדר בהצלחה:&e %anchor%"
|
||||
multi-tool:
|
||||
mode-change: "&b%device% &9: המצב השתנה ל: %mode%"
|
||||
not-shears: "&c מולטי טול לא יכול לשמש כמזמרה!"
|
||||
climbing-pick:
|
||||
dual-wielding: "&4אתה צריך להחזיק מכושי טיפוס בשתי !הידיים כדי להשתמש בהם"
|
||||
wrong-material: "&cאתה לא יכול לטפס על המשטח הזה. עיין במדריך סליים פאן למידע
|
||||
נוסף!"
|
||||
bee-suit-slow-fall: "&eכנפי הדבורה שלך יעזרו לך להגיע לקרקע בצורה איטית ובטוחה"
|
||||
not-researched: "&4אין לך מספיק ידע להבין זאת "
|
||||
unlocked: "&b אתה פתחת %research% "
|
||||
only-players: "&4 פקודה זו מיועדת רק לשחקנים"
|
||||
unknown-player: "&4 :שחקן לא מוכר &c%player%"
|
||||
no-permission: "&4 אין לך את ההרשאה הנדרשת לעשות זאת"
|
||||
usage: "&4 שימוש: &c %שימוש%"
|
||||
not-online: "&4 %שחקן%cis לא ברשת!"
|
||||
given-item: "&b ניתן לך סכום &a %amount% &7\"%item%7"
|
||||
give-item: '&b %ניתן לך %amount% &a %item%'
|
||||
give-research: "&b נתת %player% את המח\"%research%&7\""
|
||||
hungry: "&cאתה רעב מדיי כדי לעשות את זה!"
|
||||
disabled-in-world: "&4 פריט זה הושבת בעולם זה"
|
||||
disabled-item: "&4 פריט זה הושבת איך בכלל השגת את זה ?"
|
||||
no-tome-yourself: "&c אינך יכול להשתמש ב- 4 כרך של מידע צמך...."
|
||||
multimeter: '&bStored Energy: &3%stored% &b/ &3%capacity%'
|
||||
soulbound-rune:
|
||||
fail: "&c אתה יכול לקשור פריט אחד בלבד לנשמתך בכל פעם."
|
||||
success: "&a אתה קושרת פריט זה בהצלחה לנשמתך! אתה תשמור עליו כשתמות."
|
||||
research:
|
||||
start: "&7 הרוחות העתיקות לוחשות לך מילים מסתוריות לאזן"
|
||||
progress: "&7 אתה מתחיל לתהות לגביי &b%research% &e(%progress%)"
|
||||
fire-extinguish: "&7אתה כיבית את עצמך"
|
||||
cannot-place: "&c אתה לא יכול למקם את הבנייה שם!"
|
||||
no-pvp: "&cאתה לא יכול להילחם כאן!"
|
||||
radiation: |-
|
||||
&4 אתה נחשפת לקרינה קטלנית!
|
||||
&c היפטר מהפריט הרדיואקטיבי או תלבש חליפת ההסמת מלאה!
|
||||
opening-guide: "&b פותח מדריך עלול לקח כמה שניות..."
|
||||
opening-backpack: "&b פותח תרמיל עלול לקחת כמה שניות..."
|
||||
no-iron-golem-heal: "&c זה לא מטיל ברזל אתה לא יכול להשתמש בזה כדי לרפאות גולמי
|
||||
ברזל!"
|
||||
link-prompt: "&e לחץ כאן:"
|
||||
diet-cookie: "&eאתה מתחיל להרגיש מרחף...."
|
||||
invalid-item: "&4%item% &cאינו פריט בר תוקף!"
|
||||
invalid-amount: "&4%amount% &cאינו כמות ברת תוקף : המספר חייב להיות גדול מאפס!"
|
||||
invalid-research: "&4%research% &cאינו מחקר בר תוקף!"
|
||||
anvil:
|
||||
not-working: "&4אתה לא יכול להשתמש בפרטי סליים פאן בתוך סדן"
|
||||
mcmmo-salvaging: "&4אתה לא יכול להציל (לתקן) חפצי סליים פאן"
|
||||
workbench:
|
||||
not-enhanced: "&4 אתה לא יכול להשתמש בפרטי סליים פאן על שולחן עבודה רגיל"
|
||||
gps:
|
||||
geo:
|
||||
scan-required: |-
|
||||
&4-סורק גאולוגי נדרש!
|
||||
&c סרוק את הנתח הזה באמצעות סורק !גאולוגי-קודם
|
||||
waypoint:
|
||||
duplicate: "&4כבר יצרת נקודת ציון בשם: &f%waypoint%"
|
||||
new: "&eהקלד שם לנקודת הדרך החדשה שלך בצ'אט. (קודי צבע נתמכים!)"
|
||||
added: "&a נוסף בהצלחה נקודת דרך חדשה"
|
||||
max: "&4 הגעת לכמות הנקודות הדרך המרבית"
|
||||
deathpoint: |-
|
||||
&4נקודת מוות
|
||||
&7%date%
|
||||
insufficient-complexity:
|
||||
- "&4אין מספיק מורכבות ברשת ה GPS: &c%complexity%"
|
||||
- "&4a) אין לך הגדרות רשת GPS עדיין"
|
||||
- "&4b) הגדרות ה GPS שלך לא מספיק מורכבות"
|
||||
languages:
|
||||
zh-CN: "(מנדרינית(סין"
|
||||
tl: טגלית
|
||||
default: שרת ברירת מחדל
|
||||
en: אנגלית
|
||||
de: 'גרמנית '
|
||||
fr: צרפתית
|
||||
it: איטלקית
|
||||
es: ספרדית
|
||||
pl: פולנית
|
||||
sv: שוודית
|
||||
nl: הולנדית
|
||||
cs: צ'כית
|
||||
hu: הונגרית
|
||||
lv: לטבית
|
||||
ru: רוסית
|
||||
sk: סלובקית
|
||||
zh-TW: "(סינית (טייוואן"
|
||||
vi: וייטנאמי
|
||||
id: אינדונזית
|
||||
el: יווני
|
||||
he: עברית
|
||||
ar: ערבית
|
||||
af: אפריקנית
|
||||
da: דנית
|
||||
fi: פינית
|
||||
uk: אוקראינית
|
||||
ms: מלאית
|
||||
'no': נורווגית
|
||||
ja: יפנית
|
||||
fa: פרסית
|
||||
th: תאילנדי
|
||||
ro: רומנית
|
||||
pt: "(פורטוגזית (פורטוגל"
|
||||
pt-BR: "(פורטוגזית (ברזיל"
|
||||
bg: בולגרית
|
||||
ko: קוריאנית
|
||||
tr: טורקי
|
||||
hr: קרואטית
|
||||
mk: מקדונית
|
||||
sr: סרבית
|
||||
be: בלארוסית
|
||||
machines:
|
||||
GPS_CONTROL_PANEL:
|
||||
title: לוח בקרה - ג'י פי אס
|
||||
transmitters: סקירה משדר
|
||||
waypoints: סקירת נקודות דרך
|
||||
INDUSTRIAL_MINER:
|
||||
no-fuel: &c לכורה התעשייתית שלך אזל הדלק! שים את הדלק שלך בתיבה מעל.
|
||||
piston-facing: "&cהכורה התעשייתי שלך דורש בוכנות מופנות כלפי מעלה!"
|
||||
piston-space: "&cלשתי הבוכנות צריך להיות בלוק מעליהן!"
|
||||
destroyed: "&cנראה שכורה התעשייתי שלך הושמד."
|
||||
already-running: "&cהכורה התעשייתית הזה עדיין פועל."
|
||||
full-chest: "&cהתיבה של הכורה התעשייתי שלך מלאה!"
|
||||
no-permission: נראה שאין לך אישור להפעיל כאן כורה תעשייתי!&4
|
||||
finished: "&eהכורה התעשייתי שלך סיים את !%ores% ore(s)!עבודתו! הוא חצב"
|
||||
pattern-not-found: "&e סליחה לא יכולתי \n .לזהות את המתכון \nאנא הכנס את \nהפריטים
|
||||
בדפוס הנכון לתוך המתקן "
|
||||
unknown-material: "&e סליחה, לא יכולתי לזהות את הפריט במתקן שלי. אנא הכנס משהו שאני
|
||||
יודע."
|
||||
wrong-item: "&e סליחה, לא יכולתי לזהות את הפריט שאתה לחצת עליו ימני. בדוק את המתכונים
|
||||
וראה באילו פריטים אתה יכול להשתמש."
|
||||
full-inventory: "&e סליחה המלאי שלי יותר מדיי מלא!"
|
||||
in-use: "&c המלאי של בלוק זה נפתח כרגע על ידי שחקן אחר."
|
||||
ignition-chamber-no-flint: "&c תא הצתה חסר צור ופלדה."
|
||||
ANCIENT_ALTAR:
|
||||
not-enough-pedestals: "&4 המזבח אני מוקף בכמות המתאימה של כינים &c(%pedestals% /\n8( "
|
||||
unknown-catalyst: "&4 זרז לא ידוע! &c השתמש במתכון הנכון במקום זאת!"
|
||||
unknown-recipe: "&4 מתכון לא ידוע! &cהשתמש במתכון הנכון במקום!"
|
||||
ANCIENT_PEDESTAL:
|
||||
obstructed: |-
|
||||
&4הכינים נחסמו!
|
||||
&cהסר כל דבר מעל הכינים!
|
||||
HOLOGRAM_PROJECTOR:
|
||||
enter-text: "&7אנא הכנס את טקסט ההולוגרמה לצ'ט שלך. &r( קודי צבע נתמכים!)"
|
||||
inventory-title: עורך הולוגרמה
|
||||
ELEVATOR:
|
||||
no-destinations: "&4לא נמצאו יעדים "
|
||||
pick-a-floor: "&3- בחר קומה -"
|
||||
current-floor: "&e אתה נמצא כרגע על קומה:"
|
||||
click-to-teleport: "&eלחץ &7 כדי להשתגר לקומה:"
|
||||
enter-name: "&7 אנא הכנס את שם הרצפה הרצוי לצ'אט שלך. &r (קודי צבע נתמכים!)"
|
||||
named: "&2 בהצלחה נקבע שם קומה זאת: &f%floor%"
|
||||
TELEPORTER:
|
||||
teleporting: "&3משתגר...."
|
||||
teleported: "&3שוגר!"
|
||||
cancelled: "&4 השתגרות בוטלה!"
|
||||
invulnerability: "&b&l ניתן לך 30 שניות של פגיעות!"
|
||||
gui:
|
||||
title: נקודות הדרך שלך
|
||||
tooltip: לחץ לשיגור
|
||||
time: זמן משוער
|
||||
CARGO_NODES:
|
||||
must-be-placed: "&4חייב להיות מונח על תיבה או מכונה!"
|
||||
brewing_stand:
|
||||
not-working: "&4אתה לא יכול לשים חפצי סליים פאן במבשלה!"
|
||||
villagers:
|
||||
no-trading: "&4אתה לא יכול להחליף עם ויליג'רים חפצי סליים פאן!"
|
||||
cartography_table:
|
||||
not-working: "&4אתה לא יכול להשתמש בחפצי סליים פאן בשולחן קרטוגרפיה!"
|
||||
cauldron:
|
||||
no-discoloring: "&4אתה לא יכול לשנות את הצבע של שריון סליים פאן"
|
||||
android:
|
||||
scripts:
|
||||
too-long: "&c!התסריט ארוך מכדי לערוך"
|
||||
already-uploaded: "&4 התסריט הזה כבר הועלה."
|
||||
instructions:
|
||||
START: "&2 התחל תסריט"
|
||||
REPEAT: "&9תסריט חוזר"
|
||||
WAIT: "&e חכה0.5ש"
|
||||
GO_FORWARD: "&7 זוז קדימה"
|
||||
GO_UP: "&7 זוז כלפי מעלה "
|
||||
GO_DOWN: "&7זוז כלפי מטה "
|
||||
TURN_LEFT: "&7פנה שמאלה "
|
||||
TURN_RIGHT: "&7פנה ימינה "
|
||||
DIG_UP: "&bחפור כלפי מעלה "
|
||||
DIG_FORWARD: "&bחפור קדימה "
|
||||
DIG_DOWN: "&bחפור מטה "
|
||||
MOVE_AND_DIG_UP: "&b זוז ותחפור כלפי מעלה "
|
||||
MOVE_AND_DIG_FORWARD: "&b זוז ותחפור קדימה "
|
||||
MOVE_AND_DIG_DOWN: "&bזוז ותחפור כלפי מטה"
|
||||
ATTACK_MOBS_ANIMALS: "&4תקוף&c(חיות עוינות ובעלי חיים)"
|
||||
ATTACK_MOBS: "&4תקוף&c(חיות עוינות)"
|
||||
ATTACK_ANIMALS: "&4תקוף &c(בעלי חיים)"
|
||||
ATTACK_ANIMALS_ADULT: "&4תקוף &c(בעלי חיים &7[בוגרים]&c)"
|
||||
CHOP_TREE: "&c קצוץ ושתול מחדש"
|
||||
CATCH_FISH: "&bתפוס דג"
|
||||
FARM_FORWARD: "&bקצור ושתול מחדש "
|
||||
FARM_DOWN: "&bקצור ובשתול מחדש &7(מתחת לבלוק)"
|
||||
FARM_EXOTIC_FORWARD: "&bהתקדם קצור ושתול מחדש"
|
||||
FARM_EXOTIC_DOWN: "&bהתקדם קצור ושתול מחדש &7 (מתחת לבלוק"
|
||||
INTERFACE_ITEMS: "&9 דחוף את המלאי אל ממשק הפנים"
|
||||
INTERFACE_FUEL: "&c משוך דלק ממשק הפנים"
|
||||
enter-name:
|
||||
-
|
||||
- "&e אנא כתוב שם לתסריט שלך"
|
||||
uploaded:
|
||||
- "&b טוען..."
|
||||
- "&aהתסריט שלך ניטען בהצלחה!"
|
||||
rating:
|
||||
own: "&4אתה לא יכול לדרג את התסריט שלך עצמך!"
|
||||
already: "&4אתה כבר השארת דירוג לתסריט זה!"
|
||||
editor: עורך תסריט
|
||||
started: "&7 האנדרואיד שלך ממשיך את תסריט"
|
||||
stopped: "&7 האנדרואיד שלך \nעצר את התסריט "
|
||||
backpack:
|
||||
already-open: "&cסליחה התרמיל הזה פתוח במקום אחר "
|
||||
no-stack: "&cאתה לא יכול לערום תרמילים"
|
||||
inventory:
|
||||
no-access: "&4אין לך גישה לבלוק הזה"
|
@ -134,6 +134,7 @@ messages:
|
||||
wizard: "&a&oA talizmánod erősítette a Szerencse varázslatot, de néhány egyéb
|
||||
varázslatot gyengített"
|
||||
caveman: "&a&oA talizmánod adott Sietség effektet"
|
||||
wise: "&a&oA talizmánod megduplázta a dobott tapasztalat pontokat"
|
||||
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
|
||||
@ -313,6 +314,7 @@ android:
|
||||
own: "&4Nem értékelheted a saját szkriptedet!"
|
||||
already: "&4Ezt a szkriptet már értékelted!"
|
||||
editor: Szkript szerkesztő
|
||||
too-long: "&cA szkript túl hosszú a szerkesztéshez!"
|
||||
languages:
|
||||
default: Szerver-alapértelmezett
|
||||
en: Angol
|
||||
|
@ -133,6 +133,7 @@ messages:
|
||||
whirlwind: "&a&oタリスマンが飛び道具から身を護った"
|
||||
wizard: "&a&oタリスマンが高レベルの幸運を付与したが、他のエンチャントレベルは下がってしまった"
|
||||
caveman: "&a&oタリスマンが採掘速度を上昇させた"
|
||||
wise: "&a&oタリスマンが経験値のドロップを倍にした"
|
||||
soulbound-rune:
|
||||
fail: "&c一度に複数アイテムとのバインディングはできません"
|
||||
success: "&aアイテムとのバインディングが確立した!リスポーン時に当該アイテムは手繰り寄せられます"
|
||||
@ -318,7 +319,6 @@ languages:
|
||||
zh-CN: 中国語(中国)
|
||||
el: ギリシャ語
|
||||
he: ヘブライ語
|
||||
pt: ポルトガル語(ポルトガル)
|
||||
pt-BR: ポルトガル語(ブラジル)
|
||||
ar: アラビア語
|
||||
af: アフリカーンス語
|
||||
@ -331,6 +331,7 @@ languages:
|
||||
fa: ペルシア語
|
||||
th: タイ語
|
||||
ro: ルーマニア語
|
||||
pt: ポルトガル語(ポルトガル)
|
||||
bg: ブルガリア語
|
||||
ko: 韓国語
|
||||
tr: トルコ語
|
||||
|
@ -133,6 +133,7 @@ messages:
|
||||
whirlwind: "&a&o你的护身符反弹了所有射向你的投掷物"
|
||||
wizard: "&a&o你的护身符随机提高了一个附魔的等级, 但其他的附魔等级将会下降"
|
||||
caveman: "&a&o你的护身符给予了你急迫效果"
|
||||
wise: "&a&o你的护身符让掉落的经验翻倍了"
|
||||
soulbound-rune:
|
||||
fail: "&c灵魂一次只能绑定一个物品."
|
||||
success: "&a物品绑定成功! 在你死亡后此物品将不会掉落."
|
||||
@ -296,6 +297,7 @@ android:
|
||||
own: "&4你不能评价你自己的脚本!"
|
||||
already: "&4你已经给这个脚本留下评价了!"
|
||||
editor: 脚本编辑器
|
||||
too-long: "&c脚本长度已达上限, 你不能再编辑了!"
|
||||
languages:
|
||||
default: 服务器默认语言
|
||||
en: 英语
|
||||
|
@ -296,6 +296,7 @@ android:
|
||||
own: "&4你不能評價自己的程式!"
|
||||
already: "&4你已經評價過此程式!"
|
||||
editor: 程式編輯器
|
||||
too-long: "&c程式太長了,無法編輯!"
|
||||
languages:
|
||||
default: 預設
|
||||
en: 英語
|
||||
@ -318,6 +319,7 @@ languages:
|
||||
el: 希臘語
|
||||
he: 希伯來語
|
||||
pt: 葡萄牙文(葡萄牙)
|
||||
pt-BR: 葡萄牙文(巴西)
|
||||
ar: 阿拉伯文
|
||||
af: 南非語
|
||||
da: 丹麥文
|
||||
@ -329,7 +331,6 @@ languages:
|
||||
fa: 波斯語
|
||||
th: 泰語
|
||||
ro: 羅馬尼亞語
|
||||
pt-BR: 葡萄牙文(巴西)
|
||||
bg: 保加利亞語
|
||||
ko: 韓語
|
||||
tr: 土耳其
|
||||
|
@ -248,3 +248,4 @@ slimefun:
|
||||
elytra_cap: Harter Aufprall
|
||||
energy_connectors: Kupferkabel
|
||||
bee_armor: Bienen-Rüstung
|
||||
wise_talisman: Stein der Weisen
|
||||
|
@ -62,6 +62,7 @@ slimefun:
|
||||
angel_talisman: Talisman of the Angel
|
||||
fire_talisman: Talisman of the Firefighter
|
||||
caveman_talisman: Talisman of the Caveman
|
||||
wise_talisman: Talisman of the Wise
|
||||
lava_crystal: Firey Situation
|
||||
magician_talisman: Talisman of the Magician
|
||||
traveller_talisman: Talisman of the Traveller
|
||||
@ -247,3 +248,4 @@ slimefun:
|
||||
villager_rune: Reset Villager Trades
|
||||
elytra_cap: Crash Gear
|
||||
bee_armor: Bee Armor
|
||||
book_binder: Enchantment Book Binding
|
||||
|
@ -248,3 +248,4 @@ slimefun:
|
||||
elytra_cap: Equipo de choque
|
||||
energy_connectors: Conexiones Instaladas
|
||||
bee_armor: Armadura de Abeja
|
||||
wise_talisman: Talismán del Sabio
|
||||
|
@ -248,3 +248,4 @@ slimefun:
|
||||
elytra_cap: Ütközésvédelem
|
||||
energy_connectors: Vezetékes csatlakozás
|
||||
bee_armor: Méhpáncél
|
||||
wise_talisman: A Bölcs talizmánja
|
||||
|
@ -248,3 +248,5 @@ slimefun:
|
||||
elytra_cap: 衝撃緩和装備
|
||||
energy_connectors: 有線接続
|
||||
bee_armor: 蜂アーマー
|
||||
wise_talisman: 知恵のタリスマン
|
||||
book_binder: エンチャントの本の製本
|
||||
|
@ -248,3 +248,4 @@ slimefun:
|
||||
elytra_cap: 无伤落地
|
||||
energy_connectors: 有线连接
|
||||
bee_armor: 蜜蜂服
|
||||
wise_talisman: 智者的护身符
|
||||
|
@ -13,7 +13,6 @@ api-version: '1.14'
|
||||
|
||||
# (Soft) dependencies of Slimefun, we hook into these plugins.
|
||||
softdepend:
|
||||
- CS-CoreLib
|
||||
- PlaceholderAPI
|
||||
- WorldEdit
|
||||
- ClearLag
|
||||
|
@ -12,10 +12,12 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
|
||||
class TestPluginClass {
|
||||
|
||||
private static SlimefunPlugin plugin;
|
||||
|
||||
@BeforeAll
|
||||
public static void load() {
|
||||
MockBukkit.mock();
|
||||
MockBukkit.load(SlimefunPlugin.class);
|
||||
plugin = MockBukkit.load(SlimefunPlugin.class);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
@ -28,6 +30,7 @@ class TestPluginClass {
|
||||
void verifyTestEnvironment() {
|
||||
MinecraftVersion version = SlimefunPlugin.getMinecraftVersion();
|
||||
|
||||
Assertions.assertTrue(plugin.isUnitTest());
|
||||
Assertions.assertEquals(MinecraftVersion.UNIT_TEST, version);
|
||||
Assertions.assertEquals("Unit Test Environment", version.getName());
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
package io.github.thebusybiscuit.slimefun4.testing.tests.items;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
|
||||
import be.seeseemelk.mockbukkit.MockBukkit;
|
||||
import io.github.thebusybiscuit.slimefun4.core.attributes.Radioactivity;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.RadioactiveItem;
|
||||
import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
|
||||
class TestRadioactiveItem {
|
||||
|
||||
private static SlimefunPlugin plugin;
|
||||
|
||||
@BeforeAll
|
||||
public static void load() {
|
||||
MockBukkit.mock();
|
||||
plugin = MockBukkit.load(SlimefunPlugin.class);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void unload() {
|
||||
MockBukkit.unmock();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(value = Radioactivity.class)
|
||||
@DisplayName("Test radioactive items being radioactive")
|
||||
void testWikiPages(Radioactivity radioactivity) {
|
||||
Category category = TestUtilities.getCategory(plugin, "radioactivity_test");
|
||||
SlimefunItemStack stack = new SlimefunItemStack("RADIOACTIVE_" + radioactivity.name(), Material.EMERALD, "&4Radioactive!!!", "Imagine dragons");
|
||||
RadioactiveItem item = new RadioactiveItem(category, radioactivity, stack, RecipeType.NULL, new ItemStack[9]);
|
||||
|
||||
Assertions.assertEquals(radioactivity, item.getRadioactivity());
|
||||
}
|
||||
|
||||
}
|
@ -17,9 +17,15 @@ import org.junit.jupiter.params.ParameterizedTest;
|
||||
|
||||
import be.seeseemelk.mockbukkit.MockBukkit;
|
||||
import be.seeseemelk.mockbukkit.ServerMock;
|
||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.cargo.CargoInputNode;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.CargoNodeListener;
|
||||
import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
|
||||
import io.github.thebusybiscuit.slimefun4.testing.annotations.SlimefunItemsSource;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
|
||||
class TestCargoNodeListener {
|
||||
|
||||
@ -53,20 +59,42 @@ class TestCargoNodeListener {
|
||||
Assertions.assertFalse(event.isCancelled());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@Test
|
||||
@DisplayName("Test placing Cargo nodes on invalid sides of blocks")
|
||||
@SlimefunItemsSource(items = { "CARGO_INPUT_NODE", "CARGO_OUTPUT_NODE", "CARGO_OUTPUT_NODE_2" })
|
||||
void testInvalidPlacement(ItemStack item) {
|
||||
SlimefunPlugin.getRegistry().setBackwardsCompatible(true);
|
||||
void testInvalidSidePlacement() {
|
||||
Player player = server.addPlayer();
|
||||
Location l = new Location(player.getWorld(), 190, 50, 400);
|
||||
Block b = l.getBlock();
|
||||
Block against = b.getRelative(BlockFace.DOWN);
|
||||
|
||||
Category category = TestUtilities.getCategory(plugin, "cargo_test");
|
||||
SlimefunItemStack item = new SlimefunItemStack("MOCK_CARGO_NODE", new CustomItem(Material.PLAYER_HEAD, "&4Cargo node!"));
|
||||
CargoInputNode node = new CargoInputNode(category, item, RecipeType.NULL, new ItemStack[9], null);
|
||||
node.register(plugin);
|
||||
|
||||
BlockPlaceEvent event = new BlockPlaceEvent(b, b.getState(), against, item, player, true, EquipmentSlot.HAND);
|
||||
listener.onCargoNodePlace(event);
|
||||
Assertions.assertTrue(event.isCancelled());
|
||||
SlimefunPlugin.getRegistry().setBackwardsCompatible(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test placing Cargo nodes on grass")
|
||||
void testGrassPlacement() {
|
||||
Player player = server.addPlayer();
|
||||
|
||||
Location l = new Location(player.getWorld(), 300, 25, 1200);
|
||||
Block b = l.getBlock();
|
||||
b.setType(Material.GRASS);
|
||||
|
||||
Category category = TestUtilities.getCategory(plugin, "cargo_test");
|
||||
SlimefunItemStack item = new SlimefunItemStack("MOCK_CARGO_NODE_2", new CustomItem(Material.PLAYER_HEAD, "&4Cargo node!"));
|
||||
CargoInputNode node = new CargoInputNode(category, item, RecipeType.NULL, new ItemStack[9], null);
|
||||
node.register(plugin);
|
||||
|
||||
BlockPlaceEvent event = new BlockPlaceEvent(b, b.getState(), b, item, player, true, EquipmentSlot.HAND);
|
||||
listener.onCargoNodePlace(event);
|
||||
|
||||
Assertions.assertTrue(event.isCancelled());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -20,11 +20,11 @@ import be.seeseemelk.mockbukkit.MockBukkit;
|
||||
import be.seeseemelk.mockbukkit.ServerMock;
|
||||
import be.seeseemelk.mockbukkit.entity.ItemEntityMock;
|
||||
import be.seeseemelk.mockbukkit.inventory.HopperInventoryMock;
|
||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientPedestal;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.ItemPickupListener;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
||||
import me.mrCookieSlime.CSCoreLibPlugin.cscorelib2.item.CustomItem;
|
||||
|
||||
class TestItemPickupListener {
|
||||
|
||||
|
@ -6,6 +6,7 @@ import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import be.seeseemelk.mockbukkit.MockBukkit;
|
||||
@ -15,7 +16,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.PlayerProfileListener;
|
||||
import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
|
||||
|
||||
public class TestPlayerProfileListener {
|
||||
class TestPlayerProfileListener {
|
||||
|
||||
private static SlimefunPlugin plugin;
|
||||
private static PlayerProfileListener listener;
|
||||
@ -34,7 +35,8 @@ public class TestPlayerProfileListener {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPlayerLeave() throws InterruptedException {
|
||||
@DisplayName("Test PlayerProfile being marked for deletion when Player leaves")
|
||||
void testPlayerLeave() throws InterruptedException {
|
||||
Player player = server.addPlayer();
|
||||
PlayerProfile profile = TestUtilities.awaitProfile(player);
|
||||
PlayerQuitEvent event = new PlayerQuitEvent(player, "bye");
|
||||
@ -44,7 +46,8 @@ public class TestPlayerProfileListener {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnloadedPlayerLeave() {
|
||||
@DisplayName("Test PlayerProfile being unloaded when Player leaves")
|
||||
void testUnloadedPlayerLeave() {
|
||||
Player player = server.addPlayer();
|
||||
PlayerQuitEvent event = new PlayerQuitEvent(player, "bye");
|
||||
listener.onDisconnect(event);
|
||||
@ -53,7 +56,8 @@ public class TestPlayerProfileListener {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPlayerKick() throws InterruptedException {
|
||||
@DisplayName("Test PlayerProfile being marked for deletion when Player is kicked")
|
||||
void testPlayerKick() throws InterruptedException {
|
||||
Player player = server.addPlayer();
|
||||
PlayerProfile profile = TestUtilities.awaitProfile(player);
|
||||
PlayerKickEvent event = new PlayerKickEvent(player, "You're not welcome anymore", "bye");
|
||||
@ -63,7 +67,8 @@ public class TestPlayerProfileListener {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnloadedPlayerKick() {
|
||||
@DisplayName("Test PlayerProfile being unloaded when Player is kicked")
|
||||
void testUnloadedPlayerKick() {
|
||||
Player player = server.addPlayer();
|
||||
PlayerKickEvent event = new PlayerKickEvent(player, "You're not welcome anymore", "bye");
|
||||
listener.onKick(event);
|
||||
|
@ -1,6 +1,7 @@
|
||||
package io.github.thebusybiscuit.slimefun4.testing.tests.networks;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@ -172,4 +173,18 @@ class TestNetworkManager {
|
||||
Assertions.assertEquals(3, network.getSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test empty network list for null locations")
|
||||
void testNullLocations() {
|
||||
NetworkManager manager = new NetworkManager(10, false, false);
|
||||
|
||||
Optional<Network> optional = manager.getNetworkFromLocation(null, Network.class);
|
||||
Assertions.assertNotNull(optional);
|
||||
Assertions.assertFalse(optional.isPresent());
|
||||
|
||||
List<Network> list = manager.getNetworksFromLocation(null, Network.class);
|
||||
Assertions.assertNotNull(list);
|
||||
Assertions.assertTrue(list.isEmpty());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
package io.github.thebusybiscuit.slimefun4.testing.tests.profiles;
|
||||
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
|
||||
|
||||
class MockProfile extends PlayerProfile {
|
||||
|
||||
MockProfile(OfflinePlayer p) {
|
||||
super(p);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package io.github.thebusybiscuit.slimefun4.testing.tests.profiles;
|
||||
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.event.Event;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import be.seeseemelk.mockbukkit.MockBukkit;
|
||||
import be.seeseemelk.mockbukkit.ServerMock;
|
||||
import be.seeseemelk.mockbukkit.entity.OfflinePlayerMock;
|
||||
import io.github.thebusybiscuit.slimefun4.api.events.AsyncProfileLoadEvent;
|
||||
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
|
||||
|
||||
class TestAsyncProfileLoadEvent {
|
||||
|
||||
private static ServerMock server;
|
||||
|
||||
@BeforeAll
|
||||
public static void load() {
|
||||
server = MockBukkit.mock();
|
||||
MockBukkit.load(SlimefunPlugin.class);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void unload() {
|
||||
MockBukkit.unmock();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test AsyncProfileLoadEvent being thrown")
|
||||
void testEventFired() throws InterruptedException {
|
||||
server.getPluginManager().clearEvents();
|
||||
|
||||
OfflinePlayer player = new OfflinePlayerMock("EventFire");
|
||||
TestUtilities.awaitProfile(player);
|
||||
|
||||
server.getPluginManager().assertEventFired(AsyncProfileLoadEvent.class, Event::isAsynchronous);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test AsyncProfileLoadEvent#getProfile()")
|
||||
void testEventGetter() throws InterruptedException {
|
||||
server.getPluginManager().clearEvents();
|
||||
|
||||
OfflinePlayer player = new OfflinePlayerMock("GetProfile");
|
||||
PlayerProfile profile = TestUtilities.awaitProfile(player);
|
||||
|
||||
server.getPluginManager().assertEventFired(AsyncProfileLoadEvent.class, e -> e.getProfile().equals(profile));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test Profile Injection")
|
||||
void testProfileInjection() throws InterruptedException {
|
||||
OfflinePlayer player = new OfflinePlayerMock("SomePlayer");
|
||||
PlayerProfile profile = TestUtilities.awaitProfile(player);
|
||||
PlayerProfile mockProfile = new MockProfile(player);
|
||||
|
||||
AsyncProfileLoadEvent event = new AsyncProfileLoadEvent(profile);
|
||||
|
||||
Assertions.assertEquals(player.getUniqueId(), event.getPlayerUUID());
|
||||
Assertions.assertEquals(profile, event.getProfile());
|
||||
Assertions.assertFalse(event.getProfile() instanceof MockProfile);
|
||||
|
||||
event.setProfile(mockProfile);
|
||||
|
||||
Assertions.assertEquals(mockProfile, event.getProfile());
|
||||
Assertions.assertTrue(event.getProfile() instanceof MockProfile);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test Profile Mismatch")
|
||||
void testProfileMismatch() throws InterruptedException {
|
||||
OfflinePlayer player = new OfflinePlayerMock("ValidProfile");
|
||||
OfflinePlayer player2 = new OfflinePlayerMock("UnrelatedProfile");
|
||||
|
||||
PlayerProfile profile = TestUtilities.awaitProfile(player);
|
||||
PlayerProfile profile2 = TestUtilities.awaitProfile(player2);
|
||||
|
||||
AsyncProfileLoadEvent event = new AsyncProfileLoadEvent(profile);
|
||||
|
||||
// Profile is null
|
||||
Assertions.assertThrows(IllegalArgumentException.class, () -> event.setProfile(null));
|
||||
|
||||
// UUID mismatch
|
||||
Assertions.assertThrows(IllegalArgumentException.class, () -> event.setProfile(profile2));
|
||||
}
|
||||
|
||||
}
|
@ -10,6 +10,7 @@ import org.bukkit.entity.Player;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
@ -53,6 +54,7 @@ class TestResearchUnlocking {
|
||||
|
||||
@ParameterizedTest
|
||||
@DisplayName("Test Unlocking Researches")
|
||||
@Disabled(value = "Blocked by a concurrency issue in MockBukkit")
|
||||
@ValueSource(booleans = { true, false })
|
||||
void testUnlock(boolean instant) throws InterruptedException {
|
||||
SlimefunPlugin.getRegistry().setResearchingEnabled(true);
|
||||
|
@ -2,6 +2,8 @@ package io.github.thebusybiscuit.slimefun4.testing.tests.tags;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
@ -101,6 +103,19 @@ class TestSlimefunTags {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test SlimefunTag#stream()")
|
||||
void testStream() throws TagMisconfigurationException {
|
||||
SlimefunTag.reloadAll();
|
||||
|
||||
for (SlimefunTag tag : SlimefunTag.values()) {
|
||||
Set<Material> values = tag.getValues();
|
||||
Stream<Material> stream = tag.stream();
|
||||
|
||||
Assertions.assertEquals(values, stream.collect(Collectors.toSet()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test static SlimefunTag accessors")
|
||||
void testGetTag() {
|
||||
|
@ -0,0 +1,91 @@
|
||||
package io.github.thebusybiscuit.slimefun4.testing.tests.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import be.seeseemelk.mockbukkit.MockBukkit;
|
||||
import io.github.thebusybiscuit.cscorelib2.data.PersistentDataAPI;
|
||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.ChargeUtils;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class TestChargeUtils {
|
||||
|
||||
@BeforeAll
|
||||
public static void load() {
|
||||
MockBukkit.mock();
|
||||
MockBukkit.load(SlimefunPlugin.class);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void unload() {
|
||||
MockBukkit.unmock();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test setting charge")
|
||||
void testSetCharge() {
|
||||
ItemStack item = new ItemStack(Material.DIAMOND_SWORD);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
|
||||
// Make sure the lore is set
|
||||
ChargeUtils.setCharge(meta, 1, 10);
|
||||
Assertions.assertTrue(meta.hasLore());
|
||||
Assertions.assertEquals(1, meta.getLore().size());
|
||||
|
||||
// Make sure the lore is correct
|
||||
ChargeUtils.setCharge(meta, 10.1f, 100.5f);
|
||||
Assertions.assertEquals("&8\u21E8 &e\u26A1 &710.1 / 100.5 J".replace('&', ChatColor.COLOR_CHAR), meta.getLore().get(0));
|
||||
|
||||
// Make sure the persistent data was set
|
||||
Assertions.assertEquals(10.1, PersistentDataAPI.getFloat(meta, SlimefunPlugin.getRegistry().getItemChargeDataKey()), 0.001);
|
||||
|
||||
// Test exceptions
|
||||
Assertions.assertThrows(IllegalArgumentException.class, () -> ChargeUtils.setCharge(null, 1, 1));
|
||||
Assertions.assertThrows(IllegalArgumentException.class, () -> ChargeUtils.setCharge(meta, -1, 10));
|
||||
Assertions.assertThrows(IllegalArgumentException.class, () -> ChargeUtils.setCharge(meta, 100, 10));
|
||||
Assertions.assertThrows(IllegalArgumentException.class, () -> ChargeUtils.setCharge(meta, 10, -10));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getting charge")
|
||||
void testGetCharge() {
|
||||
// Test with persistent data
|
||||
ItemStack itemWithData = new ItemStack(Material.DIAMOND_SWORD);
|
||||
ItemMeta metaWithData = itemWithData.getItemMeta();
|
||||
PersistentDataAPI.setFloat(metaWithData, SlimefunPlugin.getRegistry().getItemChargeDataKey(), 10.5f);
|
||||
|
||||
Assertions.assertEquals(10.5f, ChargeUtils.getCharge(metaWithData), 0.001);
|
||||
|
||||
// Test with lore
|
||||
ItemStack itemWithLore = new ItemStack(Material.DIAMOND_SWORD);
|
||||
ItemMeta metaWithLore = itemWithLore.getItemMeta();
|
||||
metaWithLore.setLore(Collections.singletonList("&8\u21E8 &e\u26A1 &710.5 / 100.5 J".replace('&', ChatColor.COLOR_CHAR)));
|
||||
|
||||
Assertions.assertEquals(10.5, ChargeUtils.getCharge(metaWithLore), 0.001);
|
||||
Assertions.assertTrue(PersistentDataAPI.hasFloat(metaWithLore, SlimefunPlugin.getRegistry().getItemChargeDataKey()));
|
||||
|
||||
// Test no data and empty lore
|
||||
ItemStack itemWithEmptyLore = new ItemStack(Material.DIAMOND_SWORD);
|
||||
ItemMeta metaWithEmptyLore = itemWithEmptyLore.getItemMeta();
|
||||
metaWithEmptyLore.setLore(Collections.emptyList());
|
||||
|
||||
Assertions.assertEquals(0, ChargeUtils.getCharge(metaWithEmptyLore));
|
||||
|
||||
// Test no data and no lore
|
||||
ItemStack itemWithNoDataOrLore = new ItemStack(Material.DIAMOND_SWORD);
|
||||
|
||||
Assertions.assertEquals(0, ChargeUtils.getCharge(itemWithNoDataOrLore.getItemMeta()));
|
||||
|
||||
// Test exceptions
|
||||
Assertions.assertThrows(IllegalArgumentException.class, () -> ChargeUtils.getCharge(null));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user