mirror of
https://github.com/StarWishsama/Slimefun4.git
synced 2024-09-20 03:35:51 +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)
|
## :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. -->
|
<!-- "latest" IS NOT A VERSION NUMBER. -->
|
||||||
<!-- We recommend running "/sf versions" and showing us a screenshot of that. -->
|
<!-- We recommend running "/sf versions" and showing us a screenshot of that. -->
|
||||||
<!-- Make sure that the screenshot covers the entire output of that command. -->
|
<!-- Make sure that the screenshot covers the entire output of that command. -->
|
||||||
@ -51,4 +51,3 @@ assignees: ''
|
|||||||
- Server Software:
|
- Server Software:
|
||||||
- Minecraft Version:
|
- Minecraft Version:
|
||||||
- Slimefun 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/
|
/sonar/
|
||||||
/.settings/
|
/.settings/
|
||||||
/.idea/
|
/.idea/
|
||||||
|
/.vscode/
|
||||||
|
|
||||||
dependency-reduced-pom.xml
|
dependency-reduced-pom.xml
|
||||||
|
|
||||||
.classpath
|
.classpath
|
||||||
|
.factorypath
|
||||||
.project
|
.project
|
||||||
*.iml
|
*.iml
|
||||||
.DS_Store
|
.DS_Store
|
12
CHANGELOG.md
12
CHANGELOG.md
@ -28,10 +28,16 @@
|
|||||||
|
|
||||||
#### Additions
|
#### Additions
|
||||||
* Added a new language: Bulgarian
|
* 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
|
#### Changes
|
||||||
* (API) Improvements to the BlockBreakHandler
|
* (API) Improvements to the BlockBreakHandler
|
||||||
* Massive performance improvements to holograms/armorstands
|
* Massive performance improvements to holograms/armorstands
|
||||||
|
* Slimefun no longer requires CS-CoreLib to be installed
|
||||||
|
|
||||||
#### Fixes
|
#### Fixes
|
||||||
* Fixed elevator floor order
|
* Fixed elevator floor order
|
||||||
@ -48,6 +54,12 @@
|
|||||||
* Fixed some backpack opening issues
|
* Fixed some backpack opening issues
|
||||||
* Fixed Infused Hopper picking up items with a max pickup delay
|
* Fixed Infused Hopper picking up items with a max pickup delay
|
||||||
* Fixed duplication issues related to holograms/armorstands
|
* 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)
|
## Release Candidate 19 (11 Jan 2021)
|
||||||
|
|
||||||
|
10
pom.xml
10
pom.xml
@ -23,7 +23,7 @@
|
|||||||
<maven.compiler.target>1.8</maven.compiler.target>
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
|
||||||
<!-- Spigot properties -->
|
<!-- 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>
|
<spigot.javadocs>https://hub.spigotmc.org/javadocs/spigot/</spigot.javadocs>
|
||||||
|
|
||||||
<!-- Default settings for sonarcloud.io -->
|
<!-- Default settings for sonarcloud.io -->
|
||||||
@ -302,12 +302,6 @@
|
|||||||
<version>${spigot.version}-R0.1-SNAPSHOT</version>
|
<version>${spigot.version}-R0.1-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.TheBusyBiscuit</groupId>
|
|
||||||
<artifactId>CS-CoreLib</artifactId>
|
|
||||||
<version>1.7</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- Development dependencies -->
|
<!-- Development dependencies -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -393,7 +387,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.gmail.nossr50.mcMMO</groupId>
|
<groupId>com.gmail.nossr50.mcMMO</groupId>
|
||||||
<artifactId>mcMMO</artifactId>
|
<artifactId>mcMMO</artifactId>
|
||||||
<version>2.1.171</version>
|
<version>2.1.173</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
|
@ -149,7 +149,6 @@ public class ErrorReport<T extends Throwable> {
|
|||||||
stream.println();
|
stream.println();
|
||||||
|
|
||||||
stream.println("Slimefun Environment:");
|
stream.println("Slimefun Environment:");
|
||||||
stream.println(" CS-CoreLib v" + SlimefunPlugin.getCSCoreLibVersion());
|
|
||||||
stream.println(" Slimefun v" + SlimefunPlugin.getVersion());
|
stream.println(" Slimefun v" + SlimefunPlugin.getVersion());
|
||||||
stream.println(" Caused by: " + addon.getName() + " v" + addon.getPluginVersion());
|
stream.println(" Caused by: " + addon.getName() + " v" + addon.getPluginVersion());
|
||||||
stream.println();
|
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 javax.annotation.Nonnull;
|
||||||
|
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.Cancellable;
|
import org.bukkit.event.Cancellable;
|
||||||
import org.bukkit.event.Event;
|
import org.bukkit.event.Event;
|
||||||
@ -27,8 +28,11 @@ public class ResearchUnlockEvent extends Event implements Cancellable {
|
|||||||
private boolean cancelled;
|
private boolean cancelled;
|
||||||
|
|
||||||
public ResearchUnlockEvent(@Nonnull Player p, @Nonnull Research research) {
|
public ResearchUnlockEvent(@Nonnull Player p, @Nonnull Research research) {
|
||||||
|
super(!Bukkit.isPrimaryThread());
|
||||||
|
|
||||||
Validate.notNull(p, "The Player cannot be null");
|
Validate.notNull(p, "The Player cannot be null");
|
||||||
Validate.notNull(research, "Research cannot be null");
|
Validate.notNull(research, "Research cannot be null");
|
||||||
|
|
||||||
this.player = p;
|
this.player = p;
|
||||||
this.research = research;
|
this.research = research;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package io.github.thebusybiscuit.slimefun4.api.items;
|
package io.github.thebusybiscuit.slimefun4.api.items;
|
||||||
|
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
@ -92,7 +90,7 @@ public class ItemSetting<T> {
|
|||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public T getValue() {
|
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;
|
return value;
|
||||||
}
|
}
|
||||||
@ -137,6 +135,7 @@ public class ItemSetting<T> {
|
|||||||
* @param item
|
* @param item
|
||||||
* The {@link SlimefunItem} who called this method
|
* The {@link SlimefunItem} who called this method
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public void load(@Nonnull SlimefunItem item) {
|
public void load(@Nonnull SlimefunItem item) {
|
||||||
Validate.notNull(item, "Cannot apply settings for a non-existing SlimefunItem");
|
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());
|
Object configuredValue = SlimefunPlugin.getItemCfg().getValue(item.getId() + '.' + getKey());
|
||||||
|
|
||||||
if (defaultValue.getClass().isInstance(configuredValue)) {
|
if (defaultValue.getClass().isInstance(configuredValue)) {
|
||||||
// We can suppress the warning here, we did an isInstance(...) check before!
|
// We can unsafe cast here, we did an isInstance(...) check before!
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
T newValue = (T) configuredValue;
|
T newValue = (T) configuredValue;
|
||||||
|
|
||||||
if (validateInput(newValue)) {
|
if (validateInput(newValue)) {
|
||||||
this.value = newValue;
|
this.value = newValue;
|
||||||
} else {
|
} else {
|
||||||
SlimefunPlugin.logger().log(Level.WARNING, "Slimefun has found an invalid config setting in your Items.yml!");
|
// @formatter:off
|
||||||
SlimefunPlugin.logger().log(Level.WARNING, " at \"{0}.{1}\"", new Object[] { item.getId(), getKey() });
|
item.warn(
|
||||||
SlimefunPlugin.logger().log(Level.WARNING, "{0} is not a valid input!", configuredValue);
|
"We have found an invalid config setting in your Items.yml!" +
|
||||||
SlimefunPlugin.logger().log(Level.WARNING, getErrorMessage());
|
"\n at \"" + item.getId() + "." + getKey() + "\"" +
|
||||||
|
"\n " + configuredValue + " is not a valid input!" +
|
||||||
|
"\n" + getErrorMessage()
|
||||||
|
);
|
||||||
|
// @formatter:on
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.value = defaultValue;
|
this.value = defaultValue;
|
||||||
String found = configuredValue == null ? "null" : configuredValue.getClass().getSimpleName();
|
String found = configuredValue == null ? "null" : configuredValue.getClass().getSimpleName();
|
||||||
|
|
||||||
SlimefunPlugin.logger().log(Level.WARNING, "Slimefun has found an invalid config setting in your Items.yml!");
|
// @formatter:off
|
||||||
SlimefunPlugin.logger().log(Level.WARNING, "Please only use settings that are valid.");
|
item.warn(
|
||||||
SlimefunPlugin.logger().log(Level.WARNING, " at \"{0}.{1}\"", new Object[] { item.getId(), getKey() });
|
"We have found an invalid config setting in your Items.yml!" +
|
||||||
SlimefunPlugin.logger().log(Level.WARNING, "Expected \"{0}\" but found: \"{1}\"", new Object[] { defaultValue.getClass().getSimpleName(), found });
|
"\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;
|
package io.github.thebusybiscuit.slimefun4.api.player;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
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.chat.ChatColors;
|
||||||
import io.github.thebusybiscuit.cscorelib2.config.Config;
|
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.gps.Waypoint;
|
||||||
import io.github.thebusybiscuit.slimefun4.api.items.HashedArmorpiece;
|
import io.github.thebusybiscuit.slimefun4.api.items.HashedArmorpiece;
|
||||||
import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectionType;
|
import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectionType;
|
||||||
@ -56,7 +56,7 @@ import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
|
|||||||
* @see HashedArmorpiece
|
* @see HashedArmorpiece
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public final class PlayerProfile {
|
public class PlayerProfile {
|
||||||
|
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
private final String name;
|
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 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.uuid = p.getUniqueId();
|
||||||
this.name = p.getName();
|
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");
|
waypointsFile = new Config("data-storage/Slimefun/waypoints/" + uuid.toString() + ".yml");
|
||||||
|
|
||||||
|
loadProfileData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadProfileData() {
|
||||||
for (Research research : SlimefunPlugin.getRegistry().getResearches()) {
|
for (Research research : SlimefunPlugin.getRegistry().getResearches()) {
|
||||||
if (configFile.contains("researches." + research.getID())) {
|
if (configFile.contains("researches." + research.getID())) {
|
||||||
researches.add(research);
|
researches.add(research);
|
||||||
@ -95,7 +99,7 @@ public final class PlayerProfile {
|
|||||||
waypoints.add(new Waypoint(this, key, loc, waypointName));
|
waypoints.add(new Waypoint(this, key, loc, waypointName));
|
||||||
}
|
}
|
||||||
} catch (Exception x) {
|
} 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.
|
* Call this method if the Player has left.
|
||||||
* The profile can then be removed from RAM.
|
* The profile can then be removed from RAM.
|
||||||
*/
|
*/
|
||||||
public void markForDeletion() {
|
public final void markForDeletion() {
|
||||||
markedForDeletion = true;
|
markedForDeletion = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this method if this Profile has unsaved changes.
|
* Call this method if this Profile has unsaved changes.
|
||||||
*/
|
*/
|
||||||
public void markDirty() {
|
public final void markDirty() {
|
||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,9 +386,11 @@ public final class PlayerProfile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(SlimefunPlugin.instance(), () -> {
|
Bukkit.getScheduler().runTaskAsynchronously(SlimefunPlugin.instance(), () -> {
|
||||||
PlayerProfile pp = new PlayerProfile(p);
|
AsyncProfileLoadEvent event = new AsyncProfileLoadEvent(new PlayerProfile(p));
|
||||||
SlimefunPlugin.getRegistry().getPlayerProfiles().put(uuid, pp);
|
Bukkit.getPluginManager().callEvent(event);
|
||||||
callback.accept(pp);
|
|
||||||
|
SlimefunPlugin.getRegistry().getPlayerProfiles().put(uuid, event.getProfile());
|
||||||
|
callback.accept(event.getProfile());
|
||||||
});
|
});
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package io.github.thebusybiscuit.slimefun4.core;
|
package io.github.thebusybiscuit.slimefun4.core;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -61,7 +62,7 @@ public final class SlimefunRegistry {
|
|||||||
|
|
||||||
private final List<Research> researches = new LinkedList<>();
|
private final List<Research> researches = new LinkedList<>();
|
||||||
private final List<String> researchRanks = new ArrayList<>();
|
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 backwardsCompatibility;
|
||||||
private boolean automaticallyLoadItems;
|
private boolean automaticallyLoadItems;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package io.github.thebusybiscuit.slimefun4.core.attributes;
|
package io.github.thebusybiscuit.slimefun4.core.attributes;
|
||||||
|
|
||||||
|
import io.github.thebusybiscuit.slimefun4.utils.ChargeUtils;
|
||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
@ -57,7 +58,7 @@ public interface Rechargeable extends ItemAttribute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ItemMeta meta = item.getItemMeta();
|
ItemMeta meta = item.getItemMeta();
|
||||||
RechargeableHelper.setCharge(meta, charge, maximum);
|
ChargeUtils.setCharge(meta, charge, maximum);
|
||||||
item.setItemMeta(meta);
|
item.setItemMeta(meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +75,7 @@ public interface Rechargeable extends ItemAttribute {
|
|||||||
throw new IllegalArgumentException("Cannot get Item charge for null or AIR");
|
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();
|
ItemMeta meta = item.getItemMeta();
|
||||||
float currentCharge = RechargeableHelper.getCharge(meta);
|
float currentCharge = ChargeUtils.getCharge(meta);
|
||||||
float maximum = getMaxItemCharge(item);
|
float maximum = getMaxItemCharge(item);
|
||||||
|
|
||||||
// If the item is already fully charged, we abort.
|
// 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);
|
float newCharge = Math.min(currentCharge + charge, maximum);
|
||||||
RechargeableHelper.setCharge(meta, newCharge, maximum);
|
ChargeUtils.setCharge(meta, newCharge, maximum);
|
||||||
|
|
||||||
item.setItemMeta(meta);
|
item.setItemMeta(meta);
|
||||||
return true;
|
return true;
|
||||||
@ -132,7 +133,7 @@ public interface Rechargeable extends ItemAttribute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ItemMeta meta = item.getItemMeta();
|
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 the item does not have enough charge, we abort
|
||||||
if (currentCharge < charge) {
|
if (currentCharge < charge) {
|
||||||
@ -140,7 +141,7 @@ public interface Rechargeable extends ItemAttribute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float newCharge = Math.max(currentCharge - charge, 0);
|
float newCharge = Math.max(currentCharge - charge, 0);
|
||||||
RechargeableHelper.setCharge(meta, newCharge, getMaxItemCharge(item));
|
ChargeUtils.setCharge(meta, newCharge, getMaxItemCharge(item));
|
||||||
|
|
||||||
item.setItemMeta(meta);
|
item.setItemMeta(meta);
|
||||||
return true;
|
return true;
|
||||||
|
@ -30,7 +30,6 @@ class VersionsCommand extends SubCommand {
|
|||||||
|
|
||||||
sender.sendMessage(ChatColor.GRAY + "This Server uses the following setup of Slimefun:");
|
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("&a" + serverSoftware + " &2" + Bukkit.getVersion()));
|
||||||
sender.sendMessage(ChatColors.color("&aCS-CoreLib &2v" + SlimefunPlugin.getCSCoreLibVersion()));
|
|
||||||
sender.sendMessage(ChatColors.color("&aSlimefun &2v" + SlimefunPlugin.getVersion()));
|
sender.sendMessage(ChatColors.color("&aSlimefun &2v" + SlimefunPlugin.getVersion()));
|
||||||
|
|
||||||
if (SlimefunPlugin.getMetricsService().getVersion() != null) {
|
if (SlimefunPlugin.getMetricsService().getVersion() != null) {
|
||||||
|
@ -4,6 +4,9 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
@ -14,6 +17,7 @@ import org.bukkit.inventory.ItemStack;
|
|||||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||||
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
|
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
|
||||||
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideMode;
|
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.core.services.localization.Language;
|
||||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||||
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
|
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
|
||||||
@ -46,10 +50,11 @@ public final class SlimefunGuideSettings {
|
|||||||
|
|
||||||
private SlimefunGuideSettings() {}
|
private SlimefunGuideSettings() {}
|
||||||
|
|
||||||
public static <T> void addOption(SlimefunGuideOption<T> option) {
|
public static <T> void addOption(@Nonnull SlimefunGuideOption<T> option) {
|
||||||
options.add(option);
|
options.add(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
public static void openSettings(Player p, ItemStack guide) {
|
public static void openSettings(Player p, ItemStack guide) {
|
||||||
ChestMenu menu = new ChestMenu(SlimefunPlugin.getLocalization().getMessage(p, "guide.title.settings"));
|
ChestMenu menu = new ChestMenu(SlimefunPlugin.getLocalization().getMessage(p, "guide.title.settings"));
|
||||||
|
|
||||||
@ -64,6 +69,7 @@ public final class SlimefunGuideSettings {
|
|||||||
menu.open(p);
|
menu.open(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
private static void addHeader(Player p, ChestMenu menu, ItemStack guide) {
|
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) -> {
|
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);
|
SlimefunGuide.openGuide(pl, guide);
|
||||||
@ -81,7 +87,7 @@ public final class SlimefunGuideSettings {
|
|||||||
return false;
|
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,
|
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"));
|
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) {
|
private static void addConfigurableOptions(Player p, ChestMenu menu, ItemStack guide) {
|
||||||
int i = 19;
|
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) {
|
for (SlimefunGuideOption<?> option : options) {
|
||||||
if (option instanceof FireworksOption) {
|
if (option instanceof FireworksOption) {
|
||||||
FireworksOption fireworks = (FireworksOption) option;
|
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.GameMode;
|
||||||
import org.bukkit.Keyed;
|
import org.bukkit.Keyed;
|
||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
import org.bukkit.Sound;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
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.events.ResearchUnlockEvent;
|
||||||
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
|
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.core.services.localization.Language;
|
||||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||||
import io.github.thebusybiscuit.slimefun4.implementation.setup.ResearchSetup;
|
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.Category;
|
||||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||||
|
|
||||||
@ -43,9 +40,6 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
|||||||
*/
|
*/
|
||||||
public class Research implements Keyed {
|
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 NamespacedKey key;
|
||||||
private final int id;
|
private final int id;
|
||||||
private final String name;
|
private final String name;
|
||||||
@ -258,7 +252,7 @@ public class Research implements Keyed {
|
|||||||
* Whether to unlock it instantly
|
* Whether to unlock it instantly
|
||||||
*/
|
*/
|
||||||
public void unlock(@Nonnull Player p, boolean instant) {
|
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
|
* @param p
|
||||||
* The {@link Player} for which to unlock this {@link Research}
|
* The {@link Player} for which to unlock this {@link Research}
|
||||||
* @param instant
|
* @param isInstant
|
||||||
* Whether to unlock this {@link Research} instantly
|
* Whether to unlock this {@link Research} instantly
|
||||||
* @param callback
|
* @param callback
|
||||||
* A callback which will be run when the {@link Research} animation completed
|
* A callback which will be run when the {@link Research} animation completed
|
||||||
*/
|
*/
|
||||||
public void unlock(@Nonnull Player p, boolean instant, @Nonnull Consumer<Player> callback) {
|
public void unlock(@Nonnull Player p, boolean isInstant, @Nullable Consumer<Player> callback) {
|
||||||
if (!instant) {
|
PlayerProfile.get(p, new PlayerResearchTask(this, isInstant, callback));
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -329,7 +274,6 @@ public class Research implements Keyed {
|
|||||||
*/
|
*/
|
||||||
public void register() {
|
public void register() {
|
||||||
SlimefunPlugin.getResearchCfg().setDefaultValue("enable-researching", true);
|
SlimefunPlugin.getResearchCfg().setDefaultValue("enable-researching", true);
|
||||||
|
|
||||||
String path = key.getNamespace() + '.' + key.getKey();
|
String path = key.getNamespace() + '.' + key.getKey();
|
||||||
|
|
||||||
if (SlimefunPlugin.getResearchCfg().contains(path + ".enabled") && !SlimefunPlugin.getResearchCfg().getBoolean(path + ".enabled")) {
|
if (SlimefunPlugin.getResearchCfg().contains(path + ".enabled") && !SlimefunPlugin.getResearchCfg().getBoolean(path + ".enabled")) {
|
||||||
|
@ -47,7 +47,7 @@ enum SupportedLanguage {
|
|||||||
CHINESE_TAIWAN("zh-TW", true, "702a4afb2e1e2e3a1894a8b74272f95cfa994ce53907f9ac140bd3c932f9f"),
|
CHINESE_TAIWAN("zh-TW", true, "702a4afb2e1e2e3a1894a8b74272f95cfa994ce53907f9ac140bd3c932f9f"),
|
||||||
JAPANESE("ja", true, "d640ae466162a47d3ee33c4076df1cab96f11860f07edb1f0832c525a9e33323"),
|
JAPANESE("ja", true, "d640ae466162a47d3ee33c4076df1cab96f11860f07edb1f0832c525a9e33323"),
|
||||||
KOREAN("ko", true, "fc1be5f12f45e413eda56f3de94e08d90ede8e339c7b1e8f32797390e9a5f"),
|
KOREAN("ko", true, "fc1be5f12f45e413eda56f3de94e08d90ede8e339c7b1e8f32797390e9a5f"),
|
||||||
HEBREW("he", false, "1ba086a2cc7272cf5ba49c80248546c22e5ef1bab54120e8a8e5d9e75b6a"),
|
HEBREW("he", true, "1ba086a2cc7272cf5ba49c80248546c22e5ef1bab54120e8a8e5d9e75b6a"),
|
||||||
ARABIC("ar", true, "a4be759a9cf7f0a19a7e8e62f23789ad1d21cebae38af9d9541676a3db001572"),
|
ARABIC("ar", true, "a4be759a9cf7f0a19a7e8e62f23789ad1d21cebae38af9d9541676a3db001572"),
|
||||||
TURKISH("tr", true, "9852b9aba3482348514c1034d0affe73545c9de679ae4647f99562b5e5f47d09"),
|
TURKISH("tr", true, "9852b9aba3482348514c1034d0affe73545c9de679ae4647f99562b5e5f47d09"),
|
||||||
PERSIAN("fa", false, "5cd9badf1972583b663b44b1e027255de8f275aa1e89defcf77782ba6fcc652"),
|
PERSIAN("fa", false, "5cd9badf1972583b663b44b1e027255de8f275aa1e89defcf77782ba6fcc652"),
|
||||||
|
@ -47,6 +47,14 @@ public class Translators {
|
|||||||
addTranslator("dracrus", SupportedLanguage.ITALIAN, true);
|
addTranslator("dracrus", SupportedLanguage.ITALIAN, true);
|
||||||
addTranslator("prolletto64", 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
|
// Translators - Latvian
|
||||||
addTranslator("AgnisT", "NIKNAIZ", SupportedLanguage.LATVIAN, true);
|
addTranslator("AgnisT", "NIKNAIZ", SupportedLanguage.LATVIAN, true);
|
||||||
|
|
||||||
@ -91,13 +99,6 @@ public class Translators {
|
|||||||
// Translators - Ukrainian
|
// Translators - Ukrainian
|
||||||
addTranslator("SoSeDiK", SupportedLanguage.UKRAINIAN, false);
|
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
|
// Translators - Swedish
|
||||||
addTranslator("NihilistBrew", "ma1yang2", SupportedLanguage.SWEDISH, false);
|
addTranslator("NihilistBrew", "ma1yang2", SupportedLanguage.SWEDISH, false);
|
||||||
addTranslator("Tra-sh", "TurretTrash", SupportedLanguage.SWEDISH, true);
|
addTranslator("Tra-sh", "TurretTrash", SupportedLanguage.SWEDISH, true);
|
||||||
@ -137,7 +138,9 @@ public class Translators {
|
|||||||
addTranslator("Eylonnn", SupportedLanguage.HEBREW, true);
|
addTranslator("Eylonnn", SupportedLanguage.HEBREW, true);
|
||||||
addTranslator("sarhatabaot", SupportedLanguage.HEBREW, false);
|
addTranslator("sarhatabaot", SupportedLanguage.HEBREW, false);
|
||||||
addTranslator("Timotiyadeyhakesem", SupportedLanguage.HEBREW, true);
|
addTranslator("Timotiyadeyhakesem", SupportedLanguage.HEBREW, true);
|
||||||
|
addTranslator("PaladinBear", SupportedLanguage.HEBREW, true);
|
||||||
addTranslator("Molioron", SupportedLanguage.HEBREW, true);
|
addTranslator("Molioron", SupportedLanguage.HEBREW, true);
|
||||||
|
addTranslator("McAlmog", SupportedLanguage.HEBREW, true);
|
||||||
|
|
||||||
// Translators - Japanese
|
// Translators - Japanese
|
||||||
addTranslator("bito-blosh", "Bloshop", SupportedLanguage.JAPANESE, false);
|
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_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_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_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 */
|
/* Staves */
|
||||||
public static final SlimefunItemStack STAFF_ELEMENTAL = new SlimefunItemStack("STAFF_ELEMENTAL", Material.STICK, "&6Elemental Staff");
|
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 = 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_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 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_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));
|
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_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 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 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");
|
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.NumberUtils;
|
||||||
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
|
import io.github.thebusybiscuit.slimefun4.utils.tags.SlimefunTag;
|
||||||
import io.papermc.lib.PaperLib;
|
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.AContainer;
|
||||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator;
|
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator;
|
||||||
import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
||||||
@ -203,38 +204,17 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
if (minecraftVersion == MinecraftVersion.UNIT_TEST) {
|
setInstance(this);
|
||||||
|
|
||||||
|
if (isUnitTest()) {
|
||||||
// We handle Unit Tests seperately.
|
// We handle Unit Tests seperately.
|
||||||
setInstance(this);
|
|
||||||
onUnitTestStart();
|
onUnitTestStart();
|
||||||
} else if (isVersionUnsupported()) {
|
} else if (isVersionUnsupported()) {
|
||||||
// We wanna ensure that the Server uses a compatible version of Minecraft.
|
// 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);
|
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 {
|
} else {
|
||||||
// Terminate our Plugin instance
|
// The Environment has been validated.
|
||||||
setInstance(null);
|
onPluginStart();
|
||||||
|
|
||||||
// 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;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,7 +437,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
|||||||
long ms = (System.nanoTime() - timestamp) / 1000000;
|
long ms = (System.nanoTime() - timestamp) / 1000000;
|
||||||
|
|
||||||
if (ms > 1000) {
|
if (ms > 1000) {
|
||||||
return NumberUtils.roundDecimalNumber(ms / 1000.0) + "s";
|
return NumberUtils.roundDecimalNumber(ms / 1000.0) + 's';
|
||||||
} else {
|
} else {
|
||||||
return NumberUtils.roundDecimalNumber(ms) + "ms";
|
return NumberUtils.roundDecimalNumber(ms) + "ms";
|
||||||
}
|
}
|
||||||
@ -480,6 +460,16 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
|||||||
Reactor.progress = null;
|
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}.
|
* This method checks for the {@link MinecraftVersion} of the {@link Server}.
|
||||||
* If the version is unsupported, a warning will be printed to the console.
|
* 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}.
|
* This method registers all of our {@link Listener Listeners}.
|
||||||
*/
|
*/
|
||||||
private void registerListeners() {
|
private void registerListeners() {
|
||||||
|
// Old deprecated CS-CoreLib Listener
|
||||||
|
new MenuListener(this);
|
||||||
|
|
||||||
new SlimefunBootsListener(this);
|
new SlimefunBootsListener(this);
|
||||||
new SlimefunItemInteractListener(this);
|
new SlimefunItemInteractListener(this);
|
||||||
new SlimefunItemConsumeListener(this);
|
new SlimefunItemConsumeListener(this);
|
||||||
@ -984,18 +977,6 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
|
|||||||
return instance.isNewlyInstalled;
|
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
|
* This method returns a {@link Set} of every {@link Plugin} that lists Slimefun
|
||||||
* as a required or optional dependency.
|
* 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;
|
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.item.CustomItem;
|
||||||
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
||||||
import io.github.thebusybiscuit.slimefun4.core.attributes.NotHopperable;
|
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.CSCoreLibPlugin.general.Inventory.ClickAction;
|
||||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
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.BlockStorage;
|
||||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||||
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
|
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
|
||||||
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
|
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
|
||||||
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
|
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
|
||||||
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
|
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}.
|
* 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);
|
processing.remove(b);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.registerDefaultRecipes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Comparator<Integer> compareSlots(DirtyChestMenu menu) {
|
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
|
@Override
|
||||||
|
@ -1,15 +1,5 @@
|
|||||||
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines;
|
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.item.CustomItem;
|
||||||
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
||||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
|
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.BlockMenuPreset;
|
||||||
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
|
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
|
||||||
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
|
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 {
|
public class HeatedPressureChamber extends AContainer {
|
||||||
|
|
||||||
@ -73,12 +72,10 @@ public class HeatedPressureChamber extends AContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.registerDefaultRecipes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Comparator<Integer> compareSlots(DirtyChestMenu menu) {
|
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
|
@Override
|
||||||
|
@ -3,6 +3,8 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.tools;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Effect;
|
import org.bukkit.Effect;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
@ -12,7 +14,6 @@ import org.bukkit.entity.Player;
|
|||||||
import org.bukkit.event.block.BlockExplodeEvent;
|
import org.bukkit.event.block.BlockExplodeEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
|
||||||
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
||||||
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
|
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
|
||||||
import io.github.thebusybiscuit.slimefun4.core.attributes.DamageableItem;
|
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> damageOnUse = new ItemSetting<>("damage-on-use", true);
|
||||||
private final ItemSetting<Boolean> callExplosionEvent = new ItemSetting<>("call-explosion-event", false);
|
private final ItemSetting<Boolean> callExplosionEvent = new ItemSetting<>("call-explosion-event", false);
|
||||||
|
|
||||||
|
@ParametersAreNonnullByDefault
|
||||||
public ExplosiveTool(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
public ExplosiveTool(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||||
super(category, item, recipeType, 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);
|
b.getWorld().playSound(b.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 0.2F, 1F);
|
||||||
|
|
||||||
List<Block> blocks = findBlocks(b);
|
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()) {
|
if (callExplosionEvent.getValue().booleanValue()) {
|
||||||
BlockExplodeEvent blockExplodeEvent = new BlockExplodeEvent(b, blocks, 0);
|
BlockExplodeEvent blockExplodeEvent = new BlockExplodeEvent(b, blocks, 0);
|
||||||
Bukkit.getServer().getPluginManager().callEvent(blockExplodeEvent);
|
Bukkit.getServer().getPluginManager().callEvent(blockExplodeEvent);
|
||||||
@ -71,14 +74,14 @@ class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements NotPla
|
|||||||
if (!blockExplodeEvent.isCancelled()) {
|
if (!blockExplodeEvent.isCancelled()) {
|
||||||
for (Block block : blockExplodeEvent.blockList()) {
|
for (Block block : blockExplodeEvent.blockList()) {
|
||||||
if (canBreak(p, block)) {
|
if (canBreak(p, block)) {
|
||||||
breakBlock(p, item, block, fortune, drops);
|
breakBlock(p, item, block, drops);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (Block block : blocks) {
|
for (Block block : blocks) {
|
||||||
if (canBreak(p, block)) {
|
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);
|
SlimefunPlugin.getProtectionManager().logAction(p, b, ProtectableAction.BREAK_BLOCK);
|
||||||
Material material = b.getType();
|
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)) {
|
if (handler != null && !handler.onBreak(p, b, sfItem, UnregisterReason.PLAYER_BREAK)) {
|
||||||
drops.add(BlockStorage.retrieve(b));
|
drops.add(BlockStorage.retrieve(b));
|
||||||
}
|
}
|
||||||
} else if (material == Material.PLAYER_HEAD || SlimefunTag.SHULKER_BOXES.isTagged(material)) {
|
|
||||||
b.breakNaturally(item);
|
|
||||||
} else {
|
} else {
|
||||||
boolean applyFortune = SlimefunTag.FORTUNE_COMPATIBLE_ORES.isTagged(material);
|
b.breakNaturally(item);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
damageItem(p, item);
|
damageItem(p, item);
|
||||||
|
@ -10,7 +10,6 @@ import javax.annotation.Nonnull;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
@ -51,10 +50,7 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
|
|||||||
*/
|
*/
|
||||||
public class BlockListener implements Listener {
|
public class BlockListener implements Listener {
|
||||||
|
|
||||||
private final SlimefunPlugin plugin;
|
|
||||||
|
|
||||||
public BlockListener(@Nonnull SlimefunPlugin plugin) {
|
public BlockListener(@Nonnull SlimefunPlugin plugin) {
|
||||||
this.plugin = plugin;
|
|
||||||
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
plugin.getServer().getPluginManager().registerEvents(this, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,22 +62,14 @@ public class BlockListener implements Listener {
|
|||||||
if (e.getBlockReplacedState().getType().isAir()) {
|
if (e.getBlockReplacedState().getType().isAir()) {
|
||||||
SlimefunItem sfItem = BlockStorage.check(block);
|
SlimefunItem sfItem = BlockStorage.check(block);
|
||||||
|
|
||||||
if (sfItem != null) {
|
if (sfItem != null && !SlimefunPlugin.getTickerTask().isDeletedSoon(block.getLocation())) {
|
||||||
/*
|
for (ItemStack item : sfItem.getDrops()) {
|
||||||
* We can move the TickerTask synchronization to an async task to
|
if (item != null && !item.getType().isAir()) {
|
||||||
* avoid blocking the main Thread here.
|
block.getWorld().dropItemNaturally(block.getLocation(), item);
|
||||||
*/
|
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
|
||||||
if (!SlimefunPlugin.getTickerTask().isDeletedSoon(block.getLocation())) {
|
|
||||||
for (ItemStack item : sfItem.getDrops()) {
|
|
||||||
if (item != null && !item.getType().isAir()) {
|
|
||||||
SlimefunPlugin.runSync(() -> block.getWorld().dropItemNaturally(block.getLocation(), item));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockStorage.clearBlockInfo(block);
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
BlockStorage.clearBlockInfo(block);
|
||||||
}
|
}
|
||||||
} else if (BlockStorage.hasBlockInfo(e.getBlock())) {
|
} else if (BlockStorage.hasBlockInfo(e.getBlock())) {
|
||||||
// If there is no air (e.g. grass) then don't let the block be placed
|
// If there is no air (e.g. grass) then don't let the block be placed
|
||||||
@ -120,6 +108,11 @@ public class BlockListener implements Listener {
|
|||||||
return;
|
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();
|
ItemStack item = e.getPlayer().getInventory().getItemInMainHand();
|
||||||
checkForSensitiveBlockAbove(e, item);
|
checkForSensitiveBlockAbove(e, item);
|
||||||
|
|
||||||
|
@ -2,15 +2,14 @@ package io.github.thebusybiscuit.slimefun4.implementation.listeners;
|
|||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.block.BlockPlaceEvent;
|
import org.bukkit.event.block.BlockPlaceEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
|
|
||||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
||||||
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
import io.github.thebusybiscuit.slimefun4.implementation.items.cargo.CargoNode;
|
||||||
import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
|
|
||||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,25 +27,15 @@ public class CargoNodeListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onCargoNodePlace(BlockPlaceEvent e) {
|
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);
|
SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "machines.CARGO_NODES.must-be-placed", true);
|
||||||
e.setCancelled(true);
|
e.setCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isCargoNode(@Nonnull ItemStack item) {
|
private boolean isCargoNode(@Nonnull ItemStack item) {
|
||||||
if (SlimefunPlugin.getRegistry().isBackwardsCompatible()) {
|
return SlimefunItem.getByItem(item) instanceof CargoNode;
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
|||||||
import org.bukkit.event.entity.EntityDamageEvent;
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
||||||
import org.bukkit.event.entity.EntityDeathEvent;
|
import org.bukkit.event.entity.EntityDeathEvent;
|
||||||
|
import org.bukkit.event.player.PlayerExpChangeEvent;
|
||||||
import org.bukkit.event.player.PlayerItemBreakEvent;
|
import org.bukkit.event.player.PlayerItemBreakEvent;
|
||||||
import org.bukkit.event.player.PlayerToggleSprintEvent;
|
import org.bukkit.event.player.PlayerToggleSprintEvent;
|
||||||
import org.bukkit.inventory.EntityEquipment;
|
import org.bukkit.inventory.EntityEquipment;
|
||||||
@ -245,17 +246,26 @@ public class TalismanListener implements Listener {
|
|||||||
|
|
||||||
// Wizard Talisman
|
// Wizard Talisman
|
||||||
if (!enchantments.containsKey(Enchantment.SILK_TOUCH) && Enchantment.LOOT_BONUS_BLOCKS.canEnchantItem(e.getItem()) && Talisman.checkFor(e, SlimefunItems.TALISMAN_WIZARD)) {
|
if (!enchantments.containsKey(Enchantment.SILK_TOUCH) && Enchantment.LOOT_BONUS_BLOCKS.canEnchantItem(e.getItem()) && Talisman.checkFor(e, SlimefunItems.TALISMAN_WIZARD)) {
|
||||||
|
// Randomly lower some enchantments
|
||||||
for (Enchantment enchantment : enchantments.keySet()) {
|
for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
|
||||||
if (random.nextInt(100) < 40) {
|
if (entry.getValue() > 1 && random.nextInt(100) < 40) {
|
||||||
e.getEnchantsToAdd().put(enchantment, random.nextInt(3) + 1);
|
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);
|
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)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onBlockDropItems(BlockDropItemEvent e) {
|
public void onBlockDropItems(BlockDropItemEvent e) {
|
||||||
// We only want to double ores
|
// 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_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("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("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("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("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);
|
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("elytra_cap", 268, "Crash Gear", 20, SlimefunItems.ELYTRA_CAP);
|
||||||
register("energy_connectors", 269, "Wired Connections", 12, SlimefunItems.ENERGY_CONNECTOR);
|
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("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
|
@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.AutoDrier;
|
||||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.AutoEnchanter;
|
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.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.CarbonPress;
|
||||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.ChargingBench;
|
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.ChargingBench;
|
||||||
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.CropGrowthAccelerator;
|
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))
|
false, false, "caveman", 50, new PotionEffect(PotionEffectType.FAST_DIGGING, 800, 2))
|
||||||
.register(plugin);
|
.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 SlimefunItem(categories.resources, SlimefunItems.GILDED_IRON, RecipeType.SMELTERY,
|
||||||
new ItemStack[] {SlimefunItems.GOLD_24K, SlimefunItems.IRON_DUST, null, null, null, null, null, null, null})
|
new ItemStack[] {SlimefunItems.GOLD_24K, SlimefunItems.IRON_DUST, null, null, null, null, null, null, null})
|
||||||
.register(plugin);
|
.register(plugin);
|
||||||
@ -1660,6 +1666,13 @@ public final class SlimefunItemSetup {
|
|||||||
.setProcessingSpeed(4)
|
.setProcessingSpeed(4)
|
||||||
.register(plugin);
|
.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 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})
|
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)
|
.setCapacity(128)
|
||||||
@ -1765,6 +1778,13 @@ public final class SlimefunItemSetup {
|
|||||||
.setProcessingSpeed(1)
|
.setProcessingSpeed(1)
|
||||||
.register(plugin);
|
.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 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})
|
new ItemStack[] {SlimefunItems.COPPER_INGOT, null, SlimefunItems.COPPER_INGOT, null, SlimefunItems.REDSTONE_ALLOY, null, null, SlimefunItems.GOLD_6K, null})
|
||||||
.register(plugin);
|
.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.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
@ -8,32 +8,40 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
import javax.annotation.Nonnull;
|
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.NamespacedKey;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.bukkit.persistence.PersistentDataContainer;
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
|
||||||
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
|
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
|
||||||
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
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}
|
* This is just a simple helper class to provide static methods to the {@link Rechargeable}
|
||||||
* interface.
|
* interface.
|
||||||
*
|
*
|
||||||
* @author TheBusyBiscuit
|
* @author TheBusyBiscuit
|
||||||
|
* @author WalshyDev
|
||||||
*
|
*
|
||||||
* @see Rechargeable
|
* @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 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 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);
|
BigDecimal decimal = BigDecimal.valueOf(charge).setScale(2, RoundingMode.HALF_UP);
|
||||||
float value = decimal.floatValue();
|
float value = decimal.floatValue();
|
||||||
|
|
||||||
@ -55,9 +63,12 @@ final class RechargeableHelper {
|
|||||||
meta.setLore(lore);
|
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();
|
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 persistent data is available, we just return this value
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
@ -69,12 +80,14 @@ final class RechargeableHelper {
|
|||||||
for (String line : meta.getLore()) {
|
for (String line : meta.getLore()) {
|
||||||
if (REGEX.matcher(line).matches()) {
|
if (REGEX.matcher(line).matches()) {
|
||||||
String data = ChatColor.stripColor(PatternUtils.SLASH_SEPARATOR.split(line)[0].replace(LORE_PREFIX, ""));
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -53,10 +53,12 @@ public final class ItemStackWrapper extends ItemStack {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemMeta getItemMeta() {
|
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
|
* This method normally always does a .clone() operation which can be very slow.
|
||||||
// and then store that instead of creating a clone everytime.
|
* Since this class is immutable, we can simply let the super class create one copy
|
||||||
// This will significantly speed up any loop comparisons if used correctly.
|
* and then store that instead of creating a clone everytime.
|
||||||
|
* This will significantly speed up any loop comparisons if used correctly.
|
||||||
|
*/
|
||||||
if (meta == null) {
|
if (meta == null) {
|
||||||
throw new UnsupportedOperationException("This ItemStack has no ItemMeta! Make sure to check ItemStack#hasItemMeta() before accessing this method!");
|
throw new UnsupportedOperationException("This ItemStack has no ItemMeta! Make sure to check ItemStack#hasItemMeta() before accessing this method!");
|
||||||
} else {
|
} 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);
|
processing.remove(b);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
registerDefaultRecipes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParametersAreNonnullByDefault
|
@ParametersAreNonnullByDefault
|
||||||
@ -239,6 +237,8 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock,
|
|||||||
warn("Make sure to call '" + getClass().getSimpleName() + "#setProcessingSpeed(...)' before registering!");
|
warn("Make sure to call '" + getClass().getSimpleName() + "#setProcessingSpeed(...)' before registering!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerDefaultRecipes();
|
||||||
|
|
||||||
if (getCapacity() > 0 && getEnergyConsumption() > 0 && getSpeed() > 0) {
|
if (getCapacity() > 0 && getEnergyConsumption() > 0 && getSpeed() > 0) {
|
||||||
super.register(addon);
|
super.register(addon);
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,11 @@ package me.mrCookieSlime.Slimefun.api;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
@ -39,12 +40,13 @@ public class BlockInfoConfig extends Config {
|
|||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public Map<String, String> getMap() {
|
public Map<String, String> getMap() {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void store(String path, Object value) {
|
public void setValue(String path, Object value) {
|
||||||
if (value != null && !(value instanceof String)) {
|
if (value != null && !(value instanceof String)) {
|
||||||
throw new UnsupportedOperationException("Can't set \"" + path + "\" to \"" + value + "\" (type: " + value.getClass().getSimpleName() + ") because BlockInfoConfig only supports Strings");
|
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();
|
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
|
@Override
|
||||||
public Set<String> getKeys(String path) {
|
public Set<String> getKeys(String path) {
|
||||||
throw invalidType(path);
|
throw new UnsupportedOperationException("Cannot get keys for BlockInfoConfig");
|
||||||
}
|
|
||||||
|
|
||||||
private UnsupportedOperationException invalidType(String path) {
|
|
||||||
return new UnsupportedOperationException("Can't get \"" + path + "\" because BlockInfoConfig only supports String values");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public File getFile() {
|
public File getFile() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException("BlockInfoConfigs do not have a File");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileConfiguration getConfiguration() {
|
public FileConfiguration getConfiguration() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException("BlockInfoConfigs do not have a FileConfiguration");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save() {
|
public void save() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException("BlockInfoConfigs cannot be saved to a File");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(File file) {
|
public void save(File file) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException("BlockInfoConfigs cannot be saved to a File");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createFile() {
|
public void createFile() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException("BlockInfoConfigs cannot be created from a File");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reload() {
|
public void reload() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException("BlockInfoConfigs cannot be reloaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
public String toJSON() {
|
public String toJSON() {
|
||||||
return new GsonBuilder().create().toJson(data);
|
return new GsonBuilder().create().toJson(data);
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import javax.annotation.Nonnull;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
@ -27,6 +28,8 @@ import org.bukkit.configuration.file.YamlConfiguration;
|
|||||||
import org.bukkit.entity.HumanEntity;
|
import org.bukkit.entity.HumanEntity;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.Validate;
|
||||||
|
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
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) {
|
public static void store(Block block, ItemStack item) {
|
||||||
SlimefunItem sfitem = SlimefunItem.getByItem(item);
|
SlimefunItem sfitem = SlimefunItem.getByItem(item);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ class EmptyBlockData extends BlockInfoConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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!");
|
throw new UnsupportedOperationException("Cannot store values (" + path + ':' + value + " on a read-only data object!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,15 +105,18 @@ public class DirtyChestMenu extends ChestMenu {
|
|||||||
if (stack == null) {
|
if (stack == null) {
|
||||||
replaceExistingItem(slot, item);
|
replaceExistingItem(slot, item);
|
||||||
return null;
|
return null;
|
||||||
} else if (stack.getAmount() < stack.getMaxStackSize()) {
|
} else {
|
||||||
if (wrapper == null) {
|
int maxStackSize = Math.min(stack.getMaxStackSize(), toInventory().getMaxStackSize());
|
||||||
wrapper = new ItemStackWrapper(item);
|
if (stack.getAmount() < maxStackSize) {
|
||||||
}
|
if (wrapper == null) {
|
||||||
|
wrapper = new ItemStackWrapper(item);
|
||||||
|
}
|
||||||
|
|
||||||
if (ItemUtils.canStack(wrapper, stack)) {
|
if (ItemUtils.canStack(wrapper, stack)) {
|
||||||
amount -= (stack.getMaxStackSize() - stack.getAmount());
|
amount -= (maxStackSize - stack.getAmount());
|
||||||
stack.setAmount(Math.min(stack.getAmount() + item.getAmount(), stack.getMaxStackSize()));
|
stack.setAmount(Math.min(stack.getAmount() + item.getAmount(), maxStackSize));
|
||||||
item.setAmount(amount);
|
item.setAmount(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, но може да е намалило
|
wizard: "&a&oВашия Талисман Ви даде по-добро Ниво Fortune, но може да е намалило
|
||||||
Нивата на някои от другите Ви Enchantment-и"
|
Нивата на някои от другите Ви Enchantment-и"
|
||||||
caveman: "&a&oВашия Талисман Ви дава haste или познато, като бързо чупене"
|
caveman: "&a&oВашия Талисман Ви дава haste или познато, като бързо чупене"
|
||||||
|
wise: "&a&oВашия Талисман удвой вашите XP дропове"
|
||||||
soulbound-rune:
|
soulbound-rune:
|
||||||
fail: "& cМожете да свържете само един елемент с душата си наведнъж."
|
fail: "& cМожете да свържете само един елемент с душата си наведнъж."
|
||||||
success: "&aВие успешно свързахте този предмет с душата си! Когато умрете Вие
|
success: "&aВие успешно свързахте този предмет с душата си! Когато умрете Вие
|
||||||
|
@ -136,6 +136,7 @@ messages:
|
|||||||
wizard: "&a&oDein Talisman hat dein Glück-Level erhöht aber möglicherweise das
|
wizard: "&a&oDein Talisman hat dein Glück-Level erhöht aber möglicherweise das
|
||||||
Level einer anderen Verzauberung vermindert"
|
Level einer anderen Verzauberung vermindert"
|
||||||
caveman: "&a&oDein Talisman hat dir einen Abbau-Boost verschafft"
|
caveman: "&a&oDein Talisman hat dir einen Abbau-Boost verschafft"
|
||||||
|
wise: "&a&oDein Talisman hat soeben deine Erfahrungspunkte verdoppelt"
|
||||||
soulbound-rune:
|
soulbound-rune:
|
||||||
fail: "&cDu kannst nicht mehrere Items auf einmal an deine Seele binden"
|
fail: "&cDu kannst nicht mehrere Items auf einmal an deine Seele binden"
|
||||||
success: "&aDu hast dieses Item erfolgreich an deine Seele gebunden! Solltest
|
success: "&aDu hast dieses Item erfolgreich an deine Seele gebunden! Solltest
|
||||||
@ -319,6 +320,7 @@ android:
|
|||||||
own: "&4Du kannst nicht dein eigenes Skript bewerten!"
|
own: "&4Du kannst nicht dein eigenes Skript bewerten!"
|
||||||
already: "&4Du hast dieses Skript bereits bewertet!"
|
already: "&4Du hast dieses Skript bereits bewertet!"
|
||||||
editor: Skripteditor
|
editor: Skripteditor
|
||||||
|
too-long: "&cDieses Skript ist zu lang, um es zu bearbeiten!"
|
||||||
languages:
|
languages:
|
||||||
default: Server-Standard
|
default: Server-Standard
|
||||||
en: Englisch
|
en: Englisch
|
||||||
|
@ -158,6 +158,7 @@ messages:
|
|||||||
whirlwind: '&a&oYour Talisman reflected the Projectile'
|
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'
|
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'
|
caveman: '&a&oYour Talisman gave you haste'
|
||||||
|
wise: '&a&oYour Talisman has doubled your experience drops'
|
||||||
|
|
||||||
soulbound-rune:
|
soulbound-rune:
|
||||||
fail: '&cYou can only bind one item to your soul at a time.'
|
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!
|
not-rechargeable: Este ítem no puede ser cargado!
|
||||||
timings:
|
timings:
|
||||||
description: Timings para Slimefun y sus addon
|
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!"
|
verbose-player: "&4La flag verbose no puede ser usada por un jugador!"
|
||||||
unknown-flag: "&4flag desconocida: &c%flag%"
|
unknown-flag: "&4flag desconocida: &c%flag%"
|
||||||
please-wait: "&ePor favor, espere un segundo... ¡Los resultados están llegando!"
|
|
||||||
guide:
|
guide:
|
||||||
search:
|
search:
|
||||||
message: "&b¿Qué te gustaría buscar?"
|
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
|
wizard: "&a&oTu talismán te ha dado un mayor nivel de fortuna, pero pudo disminuír
|
||||||
el nivel de otros encantamientos."
|
el nivel de otros encantamientos."
|
||||||
caveman: "&a&oTu Talismán te ha dado Haste"
|
caveman: "&a&oTu Talismán te ha dado Haste"
|
||||||
|
wise: "&a&oTu Talismán ha duplicado tu drop de experiencia"
|
||||||
soulbound-rune:
|
soulbound-rune:
|
||||||
fail: "&cSolo puedes ligar un objeto a tu alma."
|
fail: "&cSolo puedes ligar un objeto a tu alma."
|
||||||
success: "&a¡Has ligado este objeto a tu alma exitosamente! No lo perderás al
|
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-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-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!"
|
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
|
bee-suit-slow-fall: "&eTus alas de Abeja te ayudarán a llegar seguro y lento al
|
||||||
piso"
|
piso"
|
||||||
|
mode-change: 'El modo de &b%device% ha cambiado a: &9%mode%'
|
||||||
machines:
|
machines:
|
||||||
pattern-not-found: "&eLo siento, no puedo reconocer esta receta. Por favor coloca
|
pattern-not-found: "&eLo siento, no puedo reconocer esta receta. Por favor coloca
|
||||||
el objeto en el patrón correcto dentro del dispensador."
|
el objeto en el patrón correcto dentro del dispensador."
|
||||||
@ -314,6 +315,7 @@ android:
|
|||||||
own: "&4¡No puedes calificar tu propio script!"
|
own: "&4¡No puedes calificar tu propio script!"
|
||||||
already: "&4¡Ya has calificado este script!"
|
already: "&4¡Ya has calificado este script!"
|
||||||
editor: Editor de Guión
|
editor: Editor de Guión
|
||||||
|
too-long: "&cEl script es demasiado largo para editar!"
|
||||||
languages:
|
languages:
|
||||||
default: Predeterminado
|
default: Predeterminado
|
||||||
en: Inglés
|
en: Inglés
|
||||||
@ -335,6 +337,7 @@ languages:
|
|||||||
zh-CN: Chino (China)
|
zh-CN: Chino (China)
|
||||||
el: Griego
|
el: Griego
|
||||||
he: Hebreo
|
he: Hebreo
|
||||||
|
pt: Portugués (Portugal)
|
||||||
ar: Árabe
|
ar: Árabe
|
||||||
af: Africano
|
af: Africano
|
||||||
da: Danés
|
da: Danés
|
||||||
@ -346,7 +349,6 @@ languages:
|
|||||||
fa: Persa
|
fa: Persa
|
||||||
th: Tailandés
|
th: Tailandés
|
||||||
ro: Rumano
|
ro: Rumano
|
||||||
pt: Portugués (Portugal)
|
|
||||||
pt-BR: Portugués (Brasil)
|
pt-BR: Portugués (Brasil)
|
||||||
bg: Búlgaro
|
bg: Búlgaro
|
||||||
ko: Coreano
|
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
|
wizard: "&a&oA talizmánod erősítette a Szerencse varázslatot, de néhány egyéb
|
||||||
varázslatot gyengített"
|
varázslatot gyengített"
|
||||||
caveman: "&a&oA talizmánod adott Sietség effektet"
|
caveman: "&a&oA talizmánod adott Sietség effektet"
|
||||||
|
wise: "&a&oA talizmánod megduplázta a dobott tapasztalat pontokat"
|
||||||
soulbound-rune:
|
soulbound-rune:
|
||||||
fail: "&cEgyszerre csak egy tárgyat köthetsz a lelkedhez."
|
fail: "&cEgyszerre csak egy tárgyat köthetsz a lelkedhez."
|
||||||
success: "&aSikeresen hozzákötötted ezt a tárgyat a lelkedhez! Megmarad, amikor
|
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!"
|
own: "&4Nem értékelheted a saját szkriptedet!"
|
||||||
already: "&4Ezt a szkriptet már értékelted!"
|
already: "&4Ezt a szkriptet már értékelted!"
|
||||||
editor: Szkript szerkesztő
|
editor: Szkript szerkesztő
|
||||||
|
too-long: "&cA szkript túl hosszú a szerkesztéshez!"
|
||||||
languages:
|
languages:
|
||||||
default: Szerver-alapértelmezett
|
default: Szerver-alapértelmezett
|
||||||
en: Angol
|
en: Angol
|
||||||
|
@ -133,6 +133,7 @@ messages:
|
|||||||
whirlwind: "&a&oタリスマンが飛び道具から身を護った"
|
whirlwind: "&a&oタリスマンが飛び道具から身を護った"
|
||||||
wizard: "&a&oタリスマンが高レベルの幸運を付与したが、他のエンチャントレベルは下がってしまった"
|
wizard: "&a&oタリスマンが高レベルの幸運を付与したが、他のエンチャントレベルは下がってしまった"
|
||||||
caveman: "&a&oタリスマンが採掘速度を上昇させた"
|
caveman: "&a&oタリスマンが採掘速度を上昇させた"
|
||||||
|
wise: "&a&oタリスマンが経験値のドロップを倍にした"
|
||||||
soulbound-rune:
|
soulbound-rune:
|
||||||
fail: "&c一度に複数アイテムとのバインディングはできません"
|
fail: "&c一度に複数アイテムとのバインディングはできません"
|
||||||
success: "&aアイテムとのバインディングが確立した!リスポーン時に当該アイテムは手繰り寄せられます"
|
success: "&aアイテムとのバインディングが確立した!リスポーン時に当該アイテムは手繰り寄せられます"
|
||||||
@ -318,7 +319,6 @@ languages:
|
|||||||
zh-CN: 中国語(中国)
|
zh-CN: 中国語(中国)
|
||||||
el: ギリシャ語
|
el: ギリシャ語
|
||||||
he: ヘブライ語
|
he: ヘブライ語
|
||||||
pt: ポルトガル語(ポルトガル)
|
|
||||||
pt-BR: ポルトガル語(ブラジル)
|
pt-BR: ポルトガル語(ブラジル)
|
||||||
ar: アラビア語
|
ar: アラビア語
|
||||||
af: アフリカーンス語
|
af: アフリカーンス語
|
||||||
@ -331,6 +331,7 @@ languages:
|
|||||||
fa: ペルシア語
|
fa: ペルシア語
|
||||||
th: タイ語
|
th: タイ語
|
||||||
ro: ルーマニア語
|
ro: ルーマニア語
|
||||||
|
pt: ポルトガル語(ポルトガル)
|
||||||
bg: ブルガリア語
|
bg: ブルガリア語
|
||||||
ko: 韓国語
|
ko: 韓国語
|
||||||
tr: トルコ語
|
tr: トルコ語
|
||||||
|
@ -133,6 +133,7 @@ messages:
|
|||||||
whirlwind: "&a&o你的护身符反弹了所有射向你的投掷物"
|
whirlwind: "&a&o你的护身符反弹了所有射向你的投掷物"
|
||||||
wizard: "&a&o你的护身符随机提高了一个附魔的等级, 但其他的附魔等级将会下降"
|
wizard: "&a&o你的护身符随机提高了一个附魔的等级, 但其他的附魔等级将会下降"
|
||||||
caveman: "&a&o你的护身符给予了你急迫效果"
|
caveman: "&a&o你的护身符给予了你急迫效果"
|
||||||
|
wise: "&a&o你的护身符让掉落的经验翻倍了"
|
||||||
soulbound-rune:
|
soulbound-rune:
|
||||||
fail: "&c灵魂一次只能绑定一个物品."
|
fail: "&c灵魂一次只能绑定一个物品."
|
||||||
success: "&a物品绑定成功! 在你死亡后此物品将不会掉落."
|
success: "&a物品绑定成功! 在你死亡后此物品将不会掉落."
|
||||||
@ -296,6 +297,7 @@ android:
|
|||||||
own: "&4你不能评价你自己的脚本!"
|
own: "&4你不能评价你自己的脚本!"
|
||||||
already: "&4你已经给这个脚本留下评价了!"
|
already: "&4你已经给这个脚本留下评价了!"
|
||||||
editor: 脚本编辑器
|
editor: 脚本编辑器
|
||||||
|
too-long: "&c脚本长度已达上限, 你不能再编辑了!"
|
||||||
languages:
|
languages:
|
||||||
default: 服务器默认语言
|
default: 服务器默认语言
|
||||||
en: 英语
|
en: 英语
|
||||||
|
@ -296,6 +296,7 @@ android:
|
|||||||
own: "&4你不能評價自己的程式!"
|
own: "&4你不能評價自己的程式!"
|
||||||
already: "&4你已經評價過此程式!"
|
already: "&4你已經評價過此程式!"
|
||||||
editor: 程式編輯器
|
editor: 程式編輯器
|
||||||
|
too-long: "&c程式太長了,無法編輯!"
|
||||||
languages:
|
languages:
|
||||||
default: 預設
|
default: 預設
|
||||||
en: 英語
|
en: 英語
|
||||||
@ -318,6 +319,7 @@ languages:
|
|||||||
el: 希臘語
|
el: 希臘語
|
||||||
he: 希伯來語
|
he: 希伯來語
|
||||||
pt: 葡萄牙文(葡萄牙)
|
pt: 葡萄牙文(葡萄牙)
|
||||||
|
pt-BR: 葡萄牙文(巴西)
|
||||||
ar: 阿拉伯文
|
ar: 阿拉伯文
|
||||||
af: 南非語
|
af: 南非語
|
||||||
da: 丹麥文
|
da: 丹麥文
|
||||||
@ -329,7 +331,6 @@ languages:
|
|||||||
fa: 波斯語
|
fa: 波斯語
|
||||||
th: 泰語
|
th: 泰語
|
||||||
ro: 羅馬尼亞語
|
ro: 羅馬尼亞語
|
||||||
pt-BR: 葡萄牙文(巴西)
|
|
||||||
bg: 保加利亞語
|
bg: 保加利亞語
|
||||||
ko: 韓語
|
ko: 韓語
|
||||||
tr: 土耳其
|
tr: 土耳其
|
||||||
|
@ -248,3 +248,4 @@ slimefun:
|
|||||||
elytra_cap: Harter Aufprall
|
elytra_cap: Harter Aufprall
|
||||||
energy_connectors: Kupferkabel
|
energy_connectors: Kupferkabel
|
||||||
bee_armor: Bienen-Rüstung
|
bee_armor: Bienen-Rüstung
|
||||||
|
wise_talisman: Stein der Weisen
|
||||||
|
@ -62,6 +62,7 @@ slimefun:
|
|||||||
angel_talisman: Talisman of the Angel
|
angel_talisman: Talisman of the Angel
|
||||||
fire_talisman: Talisman of the Firefighter
|
fire_talisman: Talisman of the Firefighter
|
||||||
caveman_talisman: Talisman of the Caveman
|
caveman_talisman: Talisman of the Caveman
|
||||||
|
wise_talisman: Talisman of the Wise
|
||||||
lava_crystal: Firey Situation
|
lava_crystal: Firey Situation
|
||||||
magician_talisman: Talisman of the Magician
|
magician_talisman: Talisman of the Magician
|
||||||
traveller_talisman: Talisman of the Traveller
|
traveller_talisman: Talisman of the Traveller
|
||||||
@ -247,3 +248,4 @@ slimefun:
|
|||||||
villager_rune: Reset Villager Trades
|
villager_rune: Reset Villager Trades
|
||||||
elytra_cap: Crash Gear
|
elytra_cap: Crash Gear
|
||||||
bee_armor: Bee Armor
|
bee_armor: Bee Armor
|
||||||
|
book_binder: Enchantment Book Binding
|
||||||
|
@ -248,3 +248,4 @@ slimefun:
|
|||||||
elytra_cap: Equipo de choque
|
elytra_cap: Equipo de choque
|
||||||
energy_connectors: Conexiones Instaladas
|
energy_connectors: Conexiones Instaladas
|
||||||
bee_armor: Armadura de Abeja
|
bee_armor: Armadura de Abeja
|
||||||
|
wise_talisman: Talismán del Sabio
|
||||||
|
@ -248,3 +248,4 @@ slimefun:
|
|||||||
elytra_cap: Ütközésvédelem
|
elytra_cap: Ütközésvédelem
|
||||||
energy_connectors: Vezetékes csatlakozás
|
energy_connectors: Vezetékes csatlakozás
|
||||||
bee_armor: Méhpáncél
|
bee_armor: Méhpáncél
|
||||||
|
wise_talisman: A Bölcs talizmánja
|
||||||
|
@ -248,3 +248,5 @@ slimefun:
|
|||||||
elytra_cap: 衝撃緩和装備
|
elytra_cap: 衝撃緩和装備
|
||||||
energy_connectors: 有線接続
|
energy_connectors: 有線接続
|
||||||
bee_armor: 蜂アーマー
|
bee_armor: 蜂アーマー
|
||||||
|
wise_talisman: 知恵のタリスマン
|
||||||
|
book_binder: エンチャントの本の製本
|
||||||
|
@ -248,3 +248,4 @@ slimefun:
|
|||||||
elytra_cap: 无伤落地
|
elytra_cap: 无伤落地
|
||||||
energy_connectors: 有线连接
|
energy_connectors: 有线连接
|
||||||
bee_armor: 蜜蜂服
|
bee_armor: 蜜蜂服
|
||||||
|
wise_talisman: 智者的护身符
|
||||||
|
@ -13,7 +13,6 @@ api-version: '1.14'
|
|||||||
|
|
||||||
# (Soft) dependencies of Slimefun, we hook into these plugins.
|
# (Soft) dependencies of Slimefun, we hook into these plugins.
|
||||||
softdepend:
|
softdepend:
|
||||||
- CS-CoreLib
|
|
||||||
- PlaceholderAPI
|
- PlaceholderAPI
|
||||||
- WorldEdit
|
- WorldEdit
|
||||||
- ClearLag
|
- ClearLag
|
||||||
|
@ -12,10 +12,12 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
|
|||||||
|
|
||||||
class TestPluginClass {
|
class TestPluginClass {
|
||||||
|
|
||||||
|
private static SlimefunPlugin plugin;
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void load() {
|
public static void load() {
|
||||||
MockBukkit.mock();
|
MockBukkit.mock();
|
||||||
MockBukkit.load(SlimefunPlugin.class);
|
plugin = MockBukkit.load(SlimefunPlugin.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
@AfterAll
|
||||||
@ -28,6 +30,7 @@ class TestPluginClass {
|
|||||||
void verifyTestEnvironment() {
|
void verifyTestEnvironment() {
|
||||||
MinecraftVersion version = SlimefunPlugin.getMinecraftVersion();
|
MinecraftVersion version = SlimefunPlugin.getMinecraftVersion();
|
||||||
|
|
||||||
|
Assertions.assertTrue(plugin.isUnitTest());
|
||||||
Assertions.assertEquals(MinecraftVersion.UNIT_TEST, version);
|
Assertions.assertEquals(MinecraftVersion.UNIT_TEST, version);
|
||||||
Assertions.assertEquals("Unit Test Environment", version.getName());
|
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.MockBukkit;
|
||||||
import be.seeseemelk.mockbukkit.ServerMock;
|
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.SlimefunPlugin;
|
||||||
|
import io.github.thebusybiscuit.slimefun4.implementation.items.cargo.CargoInputNode;
|
||||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.CargoNodeListener;
|
import io.github.thebusybiscuit.slimefun4.implementation.listeners.CargoNodeListener;
|
||||||
|
import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
|
||||||
import io.github.thebusybiscuit.slimefun4.testing.annotations.SlimefunItemsSource;
|
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 {
|
class TestCargoNodeListener {
|
||||||
|
|
||||||
@ -53,20 +59,42 @@ class TestCargoNodeListener {
|
|||||||
Assertions.assertFalse(event.isCancelled());
|
Assertions.assertFalse(event.isCancelled());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
@DisplayName("Test placing Cargo nodes on invalid sides of blocks")
|
@DisplayName("Test placing Cargo nodes on invalid sides of blocks")
|
||||||
@SlimefunItemsSource(items = { "CARGO_INPUT_NODE", "CARGO_OUTPUT_NODE", "CARGO_OUTPUT_NODE_2" })
|
void testInvalidSidePlacement() {
|
||||||
void testInvalidPlacement(ItemStack item) {
|
|
||||||
SlimefunPlugin.getRegistry().setBackwardsCompatible(true);
|
|
||||||
Player player = server.addPlayer();
|
Player player = server.addPlayer();
|
||||||
Location l = new Location(player.getWorld(), 190, 50, 400);
|
Location l = new Location(player.getWorld(), 190, 50, 400);
|
||||||
Block b = l.getBlock();
|
Block b = l.getBlock();
|
||||||
Block against = b.getRelative(BlockFace.DOWN);
|
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);
|
BlockPlaceEvent event = new BlockPlaceEvent(b, b.getState(), against, item, player, true, EquipmentSlot.HAND);
|
||||||
listener.onCargoNodePlace(event);
|
listener.onCargoNodePlace(event);
|
||||||
Assertions.assertTrue(event.isCancelled());
|
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
|
@Test
|
||||||
|
@ -20,11 +20,11 @@ import be.seeseemelk.mockbukkit.MockBukkit;
|
|||||||
import be.seeseemelk.mockbukkit.ServerMock;
|
import be.seeseemelk.mockbukkit.ServerMock;
|
||||||
import be.seeseemelk.mockbukkit.entity.ItemEntityMock;
|
import be.seeseemelk.mockbukkit.entity.ItemEntityMock;
|
||||||
import be.seeseemelk.mockbukkit.inventory.HopperInventoryMock;
|
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.SlimefunPlugin;
|
||||||
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientPedestal;
|
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientPedestal;
|
||||||
import io.github.thebusybiscuit.slimefun4.implementation.listeners.ItemPickupListener;
|
import io.github.thebusybiscuit.slimefun4.implementation.listeners.ItemPickupListener;
|
||||||
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
||||||
import me.mrCookieSlime.CSCoreLibPlugin.cscorelib2.item.CustomItem;
|
|
||||||
|
|
||||||
class TestItemPickupListener {
|
class TestItemPickupListener {
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import org.bukkit.event.player.PlayerQuitEvent;
|
|||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import be.seeseemelk.mockbukkit.MockBukkit;
|
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.implementation.listeners.PlayerProfileListener;
|
||||||
import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
|
import io.github.thebusybiscuit.slimefun4.testing.TestUtilities;
|
||||||
|
|
||||||
public class TestPlayerProfileListener {
|
class TestPlayerProfileListener {
|
||||||
|
|
||||||
private static SlimefunPlugin plugin;
|
private static SlimefunPlugin plugin;
|
||||||
private static PlayerProfileListener listener;
|
private static PlayerProfileListener listener;
|
||||||
@ -34,7 +35,8 @@ public class TestPlayerProfileListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPlayerLeave() throws InterruptedException {
|
@DisplayName("Test PlayerProfile being marked for deletion when Player leaves")
|
||||||
|
void testPlayerLeave() throws InterruptedException {
|
||||||
Player player = server.addPlayer();
|
Player player = server.addPlayer();
|
||||||
PlayerProfile profile = TestUtilities.awaitProfile(player);
|
PlayerProfile profile = TestUtilities.awaitProfile(player);
|
||||||
PlayerQuitEvent event = new PlayerQuitEvent(player, "bye");
|
PlayerQuitEvent event = new PlayerQuitEvent(player, "bye");
|
||||||
@ -44,7 +46,8 @@ public class TestPlayerProfileListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUnloadedPlayerLeave() {
|
@DisplayName("Test PlayerProfile being unloaded when Player leaves")
|
||||||
|
void testUnloadedPlayerLeave() {
|
||||||
Player player = server.addPlayer();
|
Player player = server.addPlayer();
|
||||||
PlayerQuitEvent event = new PlayerQuitEvent(player, "bye");
|
PlayerQuitEvent event = new PlayerQuitEvent(player, "bye");
|
||||||
listener.onDisconnect(event);
|
listener.onDisconnect(event);
|
||||||
@ -53,7 +56,8 @@ public class TestPlayerProfileListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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();
|
Player player = server.addPlayer();
|
||||||
PlayerProfile profile = TestUtilities.awaitProfile(player);
|
PlayerProfile profile = TestUtilities.awaitProfile(player);
|
||||||
PlayerKickEvent event = new PlayerKickEvent(player, "You're not welcome anymore", "bye");
|
PlayerKickEvent event = new PlayerKickEvent(player, "You're not welcome anymore", "bye");
|
||||||
@ -63,7 +67,8 @@ public class TestPlayerProfileListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUnloadedPlayerKick() {
|
@DisplayName("Test PlayerProfile being unloaded when Player is kicked")
|
||||||
|
void testUnloadedPlayerKick() {
|
||||||
Player player = server.addPlayer();
|
Player player = server.addPlayer();
|
||||||
PlayerKickEvent event = new PlayerKickEvent(player, "You're not welcome anymore", "bye");
|
PlayerKickEvent event = new PlayerKickEvent(player, "You're not welcome anymore", "bye");
|
||||||
listener.onKick(event);
|
listener.onKick(event);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package io.github.thebusybiscuit.slimefun4.testing.tests.networks;
|
package io.github.thebusybiscuit.slimefun4.testing.tests.networks;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@ -172,4 +173,18 @@ class TestNetworkManager {
|
|||||||
Assertions.assertEquals(3, network.getSize());
|
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.AfterEach;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.DisplayName;
|
import org.junit.jupiter.api.DisplayName;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.ValueSource;
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
@ -53,6 +54,7 @@ class TestResearchUnlocking {
|
|||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@DisplayName("Test Unlocking Researches")
|
@DisplayName("Test Unlocking Researches")
|
||||||
|
@Disabled(value = "Blocked by a concurrency issue in MockBukkit")
|
||||||
@ValueSource(booleans = { true, false })
|
@ValueSource(booleans = { true, false })
|
||||||
void testUnlock(boolean instant) throws InterruptedException {
|
void testUnlock(boolean instant) throws InterruptedException {
|
||||||
SlimefunPlugin.getRegistry().setResearchingEnabled(true);
|
SlimefunPlugin.getRegistry().setResearchingEnabled(true);
|
||||||
|
@ -2,6 +2,8 @@ package io.github.thebusybiscuit.slimefun4.testing.tests.tags;
|
|||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
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
|
@Test
|
||||||
@DisplayName("Test static SlimefunTag accessors")
|
@DisplayName("Test static SlimefunTag accessors")
|
||||||
void testGetTag() {
|
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