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

Merge branch 'master' into ShulkerShell

This commit is contained in:
LinoxGH 2020-08-20 12:21:50 +03:00 committed by GitHub
commit a54e8623d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
246 changed files with 8860 additions and 6500 deletions

View File

@ -17,13 +17,13 @@ Rules for all types of posts:
Rules for posting an Issue on GitHub:
1. This Issue Section is ONLY for Slimefun-related Issues, Issues about other Plugins or Slimefun Addons should not be posted here.
2. Please consult our [Troubleshooting Guide](#troubleshooting-guide) before posting.
2. Please consult our [Troubleshooting Guide](https://github.com/TheBusyBiscuit/Slimefun4/wiki/How-to-report-bugs) before posting.
3. Check other Issues before posting to make sure you are not posting a duplicate.
4. Do not put any Tags inside your title like [IMPORTANT], [URGENT] or [SUGGESTION]. Try to be professional by making your title as short as possible, we will assign it the required labels if necessary.
5. Do not post your Issue more than once, this is considered spam and does not benefit our community in any way. Do not repost your Issue if it was closed either.
4. Please do not put any Tags inside your title like [IMPORTANT], [URGENT] or [SUGGESTION]. Try to be professional by making your title as short as possible, we will assign it the required labels if necessary.
5. Do not post your Issue more than once, this is considered spam and does not benefit our community in any way. Do not repost your Issue if it was closed either, just leave a comment stating that the issue has still persisted and give more context on it.
6. Give us all available information right away, it may be a bit of time-wasting for us to keep asking for more Info. And this includes any Information to reproduce your Issue step-by-step.
7. Check whether there are newer versions available than the ones you are using, it might be that your Issue has been fixed already.
8. All text logs must be posted via a link to http://pastebin.com or similiar websites.
8. All text logs must be posted via a link to https://pastebin.com/ or similiar websites, long logs are very hard to read and get weirdly formatted when you post them on here. Using a proper pasting site allows us to keep things clean and easy to read.
Your Issue will be CLOSED WITHOUT WARNING if we think you violated these Rules.
@ -35,26 +35,3 @@ Guidelines for making a Pull Request on GitHub:
2. Try to make your values configurable in the config.yml / Items.yml or any additional file. This may not be necessary at every instance but it does give the end-users a way to customize their experience.
3. If your Pull Request is made in response to an Issue opened on GitHub, comment on that Issue and reference your Pull Request to show that you are proposing a fix for it.
4. Name your commits appropriately. Standards like "Add files via upload" or "Update Readme.md" are lame. Make sure that the commit message stands for it's changes. (e.g. "Fixed Furnaces duplicating Items")
## Troubleshooting Guide
### Step 1: Check whether you have installed Slimefun correctly
Slimefun requires [CS-CoreLib](http://dev.bukkit.org/bukkit-plugins/cs-corelib) to run.
If it has not been installed automatically for you, then please download & install it manually.
### Step 2: Check whether you are running on the latest Versions
Both, [Slimefun](http://dev.bukkit.org/bukkit-plugins/slimefun/files) and [CS-CoreLib](http://dev.bukkit.org/bukkit-plugins/cs-corelib/files) are updated from time to time.
You should be sure that you run the latest Versions (at the time you post your Issue) of both Plugins.
### Step 3: Does it have to do with Items called 'CS-CoreLib's Head'?
Well in that case, you have been the victim of corruption, unless you have an Error/Crash Report that we can work with, there is literally nothing we can do about it.
Corrupting Files/Data can happen from time to time and getting completely rid of it would require a ton of work and even then it is still not completely impossible to occur.
### Step 4: Do you get an Error, do you have an Error Report?
Check your /plugins/Slimefun/error-reports/ directory and if it contains any Files, then please upload those to http://pastebin.com
and provide us with a link.
When providing us Errors from your Server Log MAKE SURE THEY ARE ERRORS.
It has happened more often than you may think that people send us messages.
Try to read the suspected 'Error' before uploading it to http://pastebin.com
If it says "Please install CS-CoreLib", then you may want to rethink whether you want to ask us what it means...

View File

@ -7,24 +7,46 @@ assignees: ''
---
## Description (Required)
<!-- A clear and detailed description of what exactly the Issue consists of. -->
<!-- FILL IN THE FORM BELOW -->
## Steps to reproduce the Issue (Required)
## Description (REQUIRED)
<!-- A clear and detailed description of what went wrong. -->
<!-- The more information you can provide, the easier we can handle this problem. -->
<!-- Start writing below this line -->
## Steps to reproduce the Issue (REQUIRED)
<!-- Tell us the exact steps to reproduce this issue, the more detailed the easier we can reproduce it. -->
<!-- Youtube Videos and Screenshots are recommended! -->
<!-- Start writing below this line -->
## Expected behavior (Required)
<!-- What did you expect to happen? -->
## Server Log / Error Report
<!-- Take a look at your Server Log and please provide any error reports you can find via https://pastebin.com/ -->
<!-- We may discard your Issue if you just post it here, as it's unreadable for us. Please use Pastebin! -->
## Expected behavior (REQUIRED)
<!-- What were you expecting to happen? -->
<!-- What do you think would have been the correct behaviour? -->
<!-- Start writing below this line -->
## Environment (Required)
<!-- We may also close your Issue if you are not providing the exact version numbers. -->
## Server Log
<!-- Take a look at your Server Log and post any errors you can find via https://pastebin.com/ -->
<!-- If you are unsure about it, post your full log, you can find it under /logs/latest.log -->
<!-- Start writing below this line -->
## Error Reports
<!-- Check the folder /plugins/Slimefun/error-reports/ and upload all files inside that folder. -->
<!-- You can also post these files via https://pastebin.com/ -->
<!-- Start writing below this line -->
## Environment (REQUIRED)
<!-- Any info without the exact version numbers will be closed! -->
<!-- "latest" IS NOT A VERSION NUMBER. -->
<!-- You can also just run "/sf versions" and show 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. -->
<!-- If your issue is related to other plugins, make sure to include the versions of these plugins too! -->
- Server Software (Spigot/Paper):
- Minecraft Version:
- Slimefun Version:
- CS-CoreLib Version:

View File

@ -1,12 +1,15 @@
name: Close invalid Issue
on:
issues:
on:
issues:
types: [opened]
jobs:
comment:
name: Invalid Issues
runs-on: ubuntu-latest
if: contains(github.event.issue.labels.*.name, 'Bug Report') == false
steps:
- name: Close Issue
@ -29,6 +32,6 @@ jobs:
body: |-
Your issue seems to be missing our template.
[Click here to create a bug report](https://github.com/TheBusyBiscuit/Slimefun4/issues/new/choose)
Please remember that this Bug Tracker is exclusively reserved for Bug reports, any other form
of discussion, like suggestions or questions should be posted on our discord server (You can find a link [on our main page](https://github.com/TheBusyBiscuit/Slimefun4#discord)).

View File

@ -1,6 +1,7 @@
name: Respond to closed Issue
on:
issues:
on:
issues:
types: [closed]
jobs:
@ -28,20 +29,19 @@ jobs:
token: ${{ secrets.ACCESS_TOKEN }}
issue_number: ${{ github.event.issue.number }}
body: |-
Your issue was closed, it may fall under one or more of the following categories.
Your issue has been closed by an admin, it may fall under one or more of the following categories.
**Please wait for an admin to tick off the points that apply.**
Please respond below, if you have any questions.
Do **not** open a new Issue unless explicitly told otherwise, comment below or edit your post instead.
<hr>
* [ ] You did not follow our template. Please follow the Issue template to help us identify your issue more effectively.
* [ ] You did not provide any information about your versions (We absolutely need the exact version numbers that are installed on your Server, \"latest\" is not helpful)
* [ ] You did not provide a proper description to the problem. Try to write at least 4-6 sentences on how to reproduce this.
* [ ] You did not provide a proper description to the problem. Try to write at least 4-6 sentences and/or provide screenshots or videos on how to reproduce this.
* [ ] We were unable to reproduce issue, if you think your issue still persists then please comment down below and give a better description on how to reproduce it.
* [ ] Your issue was posted in a foreign language, we only accept english issues on here.
* [ ] Your issue is not a bug, it is either intended or something we cannot change.
* [ ] Your issue is not a bug, it is intended to work this way.
* [ ] Your issue is not really a bug, it is a limitation or simply something we have no control over.
* [ ] Your issue is not a bug, please only use this issue tracker to report bugs. Any other kind of communication should happen on discord.
* [ ] Your issue was already reported, it is a duplicate. Check the other issues first before posting!
* [ ] Your issue has already been reported before, it is a duplicate. Check the other issues first before posting!
* [ ] You posted an error without using pastebin. Please always post errors via pastebin otherwise they become nearly unreadable.
* [ ] You seem to be reporting multiple bugs at once. Please make a seperate issue for each bug you encountered, so we can properly handle them individually.
* [ ] Your issue has already been fixed in a later version of Slimefun or CS-CoreLib, you should update.
@ -50,5 +50,8 @@ jobs:
* [ ] You are using an unsupported version of Minecraft. We only provide support for the Minecraft versions Slimefun was developed for, older versions are not supported anymore.
* [ ] You are using a \"stable\" version of Slimefun (prefixed with \"RC - \"), your issue may have been fixed in a development build, so we only accept bug reports from those.
* [ ] You are on the wrong issue tracker. We would like to remind you that this Issue Tracker is **only for Slimefun**. To report bugs on any addons, head to the corresponding issue tracker of that addon.
<hr>
Please respond below, if you have any further questions.
Do **not** open a new Issue unless explicitly told otherwise, comment below or edit your post instead.<br>
Make sure to check out our article on [How to report bugs](https://github.com/TheBusyBiscuit/Slimefun4/wiki/How-to-report-bugs) for even more information.

View File

@ -9,6 +9,7 @@ on:
jobs:
report:
name: Discord Webhook
runs-on: ubuntu-latest
if: github.repository == 'TheBusyBiscuit/Slimefun4'

View File

@ -1,12 +1,15 @@
name: Mark Issue as duplicate
on:
issue_comment:
on:
issue_comment:
types: [created]
jobs:
comment:
name: Mark Issue as duplicate
runs-on: ubuntu-latest
if: contains(github.event.comment.body, 'Duplicate of ')
steps:
- name: Add label to the Issue

View File

@ -17,6 +17,7 @@ on:
jobs:
build:
name: Maven build
runs-on: ubuntu-latest
steps:

View File

@ -1,18 +1,19 @@
name: Translation Notifier
on:
on:
push:
branches:
- master
paths:
- 'src/main/resources/languages/**_en.yml'
jobs:
notify:
name: Translation-Notifier
runs-on: ubuntu-latest
if: github.repository == 'TheBusyBiscuit/Slimefun4'
steps:
- name: Discord Notification
uses: Ilshidur/action-discord@master

View File

@ -1,19 +1,19 @@
name: Changelog Populator
on:
on:
push:
branches:
- master
paths:
- 'CHANGELOG.md'
jobs:
populate:
name: Changelog Generator
runs-on: ubuntu-latest
if: github.repository == 'TheBusyBiscuit/Slimefun4'
steps:
- name: TOC Generator
uses: technote-space/toc-generator@v2.4.0

26
.github/workflows/url-checker.yml vendored Normal file
View File

@ -0,0 +1,26 @@
name: URL Validator
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
name: URL Checker
runs-on: ubuntu-latest
steps:
- name: URL-checker
uses: SuperKogito/URLs-checker@0.2.1
with:
git_path: https://github.com/TheBusyBiscuit/Slimefun4
file_types: .md,.java,.yml
print_all: False
retry_count: 2
## These URLs will always be correct, even if their services may be offline right now
white_listed_patterns: http://textures.minecraft.net/texture/,https://pastebin.com/,https://www.spigotmc.org/threads/spigot-bungeecord-1-16-1.447405/#post-3852349

25
.github/workflows/yaml-linter.yml vendored Normal file
View File

@ -0,0 +1,25 @@
name: YAML Linter
on:
push:
paths:
- '**.yml'
pull_request:
branches:
- master
paths:
- '**.yml'
jobs:
linter:
name: YAML Linter
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v1
- name: YAML Linter
uses: ibiqlik/action-yamllint@v1.0.0
with:
config_file: '.github/yaml-lint.yml'

17
.github/yaml-lint.yml vendored Normal file
View File

@ -0,0 +1,17 @@
extends: default
locale: en_US.UTF-8
yaml-files:
- '*.yml'
rules:
line-length:
max: 160
level: warning
## We don't need indentation warnings
indentation: disable
trailing-spaces:
ignore: |
/src/main/resources/languages/*.yml

View File

@ -2,7 +2,8 @@
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of contents**
- [Release Candidate 15 (TBD)](#release-candidate-15-tbd)
- [Release Candidate 16 (TBD)](#release-candidate-16-tbd)
- [Release Candidate 15 (01 Aug 2020)](#release-candidate-15-01-aug-2020)
- [Release Candidate 14 (12 Jul 2020)](#release-candidate-14-12-jul-2020)
- [Release Candidate 13 (16 Jun 2020)](#release-candidate-13-16-jun-2020)
- [Release Candidate 12 (27 May 2020)](#release-candidate-12-27-may-2020)
@ -20,18 +21,70 @@
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Release Candidate 15 (TBD)
## Release Candidate 16 (TBD)
#### Additions
* Added an option for Industrial Miners to mine Ancient Debris
* Added a new language: Korean
* (API) Added support for adding custom Piglin Barter drops
* (API) Added BlockPlacerPlaceEvent
* (API) Added ToolUseHandler
* Added "Sand -> Sandstone" recipe to the Electric Press
* Added "Red Sand -> Red Sandstone" recipe to the Electric Press
* Industrial Miners can now also mine Gilded Blackstone
* Added a config option to disable Players from burning when exposed to radiation
#### Changes
* Performance improvement for Programmable Android rotations
* Removed Gravel -> Flint recipe from the Grind stone
* Performance improvements for miner talismans
* Performance improvements for idling Enhanced Furnaces when using Paper
* Performance improvements for Rainbow Blocks
* Crafting a Rag now yields two items
* Small performance improvements for Slimefun guides
* Small performance improvements for Cargo networks
* Small performance improvements for Miner Androids
#### Fixes
* Fixed Programmable Androids rotating in the wrong direction
* Fixed #2176
* Fixed #2164
* Fixed #2147
* Fixed #2179
* Fixed Reinforced Spawners not working sometimes
* Fixed Explosive Pickaxe not handling normal Shulker boxes correctly
* Fixed #2103
* Fixed #2184
* Fixed #2183
* Fixed #2181
* Fixed #2180
* Fixed #2122
* Fixed #2168
* Fixed #2203
* Fixed #2205
* Fixed #2209
* Fixed #2217
* Fixed Miner Talisman sending messages when drops were not even doubled
* Fixed #2077
* Fixed #2207
* Fixed ChestTerminal timings showing up as cargo nodes
* Fixed timings reports never arriving sometimes
* Fixed #2138
## Release Candidate 15 (01 Aug 2020)
#### Additions
* Added "Bone Block -> Bone meal" recipe to the Grind Stone
* Added a [Metrics module](https://github.com/Slimefun/MetricsModule) which allows us to release updates to metrics (bStats) independently from the main plugin
* Added "Compressed Carbon -> Carbon" recipe to the Ore Crusher
* Added "Carbon -> Coal" recipe to the Ore Crusher
* Added an option to disable the message "Ignoring duplicate block"
* Added Iron Golem Assembler
* Added Reinforced Cloth
* Added Bee protection to Hazmat Suit
* Added Enchantment Rune
* Added Tape Measure
* Added a permission node for /sf debug_fish
#### Changes
* Refactored and reworked the Generator API
@ -44,6 +97,12 @@
* Optimized Cargo networks for Paper
* Optimized Multiblocks for Paper
* Optimized Enhanced Furnaces for Paper
* Optimized Programmable Androids for Paper
* General performance improvements for Talismans
* General performance improvements for GPS Emergency Transmitters
* General performance improvements for Infused Magnets
* Ancient Altars now support for protection plugins
* Ancient Pedestals now support for protection plugins
#### Fixes
* Fixed Slimefun Armor sometimes not applying its effects
@ -51,6 +110,20 @@
* Fixed #2093
* Fixed #2086
* Fixed #1894
* Fixed #2097
* Fixed Wither Assembler requiring more items than it actually consumes
* Fixed Metrics not updating automatically
* Fixed #2143
* Fixed #2145
* Fixed #2151
* Fixed old Talismans not working
* Fixed Talismans sometimes not getting consumed properly
* Fixed old Infused Magnets not working
* Fixed old GPS Emergency Transmitters not working
* Fixed #2156
* Fixed #2165
* Fixed #2162
* Fixed #2166
## Release Candidate 14 (12 Jul 2020)

View File

@ -14,6 +14,7 @@ Check out our [Addons](https://github.com/TheBusyBiscuit/Slimefun4/wiki/Addons),
### Quick navigation
* **[Download Slimefun4](#download-slimefun-4)**
* **[Screenshots](#screenshots)**
* **[Discord Support Server](#discord)**
* **[Bug Tracker](https://github.com/TheBusyBiscuit/Slimefun4/issues)**
* **[Wiki](https://github.com/TheBusyBiscuit/Slimefun4/wiki)**
@ -54,6 +55,16 @@ While "stable" builds most definitely contain more bugs than development builds
</details>
## Screenshots
So what does Slimefun look like?<br>
Well, we asked some users on our [Discord server](#discord) to send us some screenshots, so see for yourself:
| Reactors and electricity | Awesome factories | Magic and Altars |
| :-------------------------------------------: | :--------------------------------------: | :----------------------------------------: |
| ![](https://raw.githubusercontent.com/Slimefun/Slimefun-Wiki/master/images/showcase1.png) | ![](https://raw.githubusercontent.com/Slimefun/Slimefun-Wiki/master/images/showcase6.png) | ![](https://raw.githubusercontent.com/Slimefun/Slimefun-Wiki/master/images/showcase5.png) |
| *Screenshot provided by HamtaBot#0001* | *Screenshot provided by Piͭxͪeͤl (mnb)#5049* | *Screenshot provided by Kilaruna#4981* |
| ![](https://raw.githubusercontent.com/Slimefun/Slimefun-Wiki/master/images/showcase4.png) | ![](https://raw.githubusercontent.com/Slimefun/Slimefun-Wiki/master/images/showcase3.png) | ![](https://raw.githubusercontent.com/Slimefun/Slimefun-Wiki/master/images/showcase2.png) |
| *Screenshot provided by GalaxyKat11#3816* | *Screenshot provided by TamThan#7987* | *Screenshot provided by Kilaruna#4981* |
## Discord
You can find Slimefun's community on Discord and connect with **over 2000** users of this plugin from all over the world.<br>
Click the badge down below to join the server for suggestions/questions or other discussions about this plugin.<br>
@ -181,5 +192,5 @@ This information includes (but is not limited to)
* date of the last commit to this repository
</details>
Additionally the plugin connects to https://mojang.com/ to retrieve the Minecraft skins of our contributors (if possible).<br>
Additionally the plugin connects to [textures.minecraft.net](https://www.minecraft.net/en-us) to retrieve the Minecraft skins of our contributors (if possible).<br>
Note that Slimefun is not associated with `Mojang Studios` or Minecraft.

30
pom.xml
View File

@ -4,7 +4,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.thebusybiscuit</groupId>
<groupId>com.github.thebusybiscuit</groupId>
<artifactId>Slimefun</artifactId>
<!-- Our default version will be UNOFFICIAL, this will prevent auto updates -->
@ -22,7 +22,7 @@
<maven.compiler.target>1.8</maven.compiler.target>
<!-- Spigot properties -->
<spigot.version>1.16.1</spigot.version>
<spigot.version>1.16.2</spigot.version>
<spigot.javadocs>https://hub.spigotmc.org/javadocs/spigot/</spigot.javadocs>
<!-- Default settings for sonarcloud.io -->
@ -47,6 +47,16 @@
</licenses>
<repositories>
<repository>
<id>sonatype-snapshots</id>
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
@ -57,7 +67,7 @@
</repository>
<repository>
<id>paper-repo</id>
<url>https://repo.destroystokyo.com/repository/maven-public/</url>
<url>https://papermc.io/repo/repository/maven-public/</url>
</repository>
<repository>
<id>worldedit-repo</id>
@ -303,14 +313,14 @@
</dependency>
<dependency>
<groupId>com.github.seeseemelk</groupId>
<artifactId>MockBukkit</artifactId>
<version>v1.15-d952559324-1</version>
<artifactId>MockBukkit-v1.15</artifactId>
<version>0.3.1-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.4.4</version>
<version>3.5.2</version>
<scope>test</scope>
</dependency>
@ -318,7 +328,7 @@
<dependency>
<groupId>com.github.TheBusyBiscuit</groupId>
<artifactId>CS-CoreLib2</artifactId>
<version>0.24</version>
<version>0.25</version>
<scope>compile</scope>
</dependency>
<dependency>
@ -330,7 +340,7 @@
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-java</artifactId>
<version>3.8.06</version>
<version>3.9.00</version>
<exclusions>
<exclusion>
<groupId>com.google.code.gson</groupId>
@ -341,7 +351,7 @@
<dependency>
<groupId>io.papermc</groupId>
<artifactId>paperlib</artifactId>
<version>1.0.4</version>
<version>1.0.5</version>
<scope>compile</scope>
</dependency>
@ -364,7 +374,7 @@
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.10.6</version>
<version>2.10.9</version>
<scope>provided</scope>
</dependency>
<dependency>

View File

@ -84,7 +84,7 @@ public class ErrorReport {
addon.getLogger().log(Level.WARNING, "");
addon.getLogger().log(Level.WARNING, "An Error occurred! It has been saved as: ");
addon.getLogger().log(Level.WARNING, "/plugins/Slimefun/error-reports/{0}", file.getName());
addon.getLogger().log(Level.WARNING, "Please put this file on https://pastebin.com and report this to the developer(s).");
addon.getLogger().log(Level.WARNING, "Please put this file on https://pastebin.com/ and report this to the developer(s).");
if (addon.getBugTrackerURL() != null) {
addon.getLogger().log(Level.WARNING, "Bug Tracker: {0}", addon.getBugTrackerURL());

View File

@ -45,14 +45,6 @@ public class AncientAltarCraftEvent extends PlayerEvent implements Cancellable {
this.output = output;
}
public static HandlerList getHandlerList() {
return handlers;
}
public HandlerList getHandlers() {
return handlers;
}
/**
* This method returns the main altar's block {@link Block}
*
@ -95,4 +87,13 @@ public class AncientAltarCraftEvent extends PlayerEvent implements Cancellable {
cancelled = cancel;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
}

View File

@ -34,14 +34,6 @@ public class AndroidMineEvent extends Event implements Cancellable {
this.android = android;
}
public static HandlerList getHandlerList() {
return handlers;
}
public HandlerList getHandlers() {
return handlers;
}
/**
* This method returns the mined {@link Block}
*
@ -71,4 +63,13 @@ public class AndroidMineEvent extends Event implements Cancellable {
cancelled = cancel;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
}

View File

@ -27,14 +27,6 @@ public class AutoDisenchantEvent extends Event implements Cancellable {
this.item = item;
}
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
/**
* This returns the {@link ItemStack} that is being disenchanted.
*
@ -54,4 +46,13 @@ public class AutoDisenchantEvent extends Event implements Cancellable {
this.cancelled = cancel;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
}

View File

@ -0,0 +1,113 @@
package io.github.thebusybiscuit.slimefun4.api.events;
import org.apache.commons.lang.Validate;
import org.bukkit.block.Block;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.block.BlockEvent;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.BlockPlacer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
/**
* This {@link Event} is fired whenever a {@link BlockPlacer} wants to place a {@link Block}.
*
* @author TheBusyBiscuit
*
*/
public class BlockPlacerPlaceEvent extends BlockEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private final Block blockPlacer;
private ItemStack placedItem;
private boolean cancelled = false;
private boolean locked = false;
/**
* This creates a new {@link BlockPlacerPlaceEvent}.
*
* @param blockPlacer
* The {@link BlockPlacer}
* @param placedItem
* The {@link ItemStack} of the {@link Block} that was placed
* @param block
* The placed {@link Block}
*/
public BlockPlacerPlaceEvent(Block blockPlacer, ItemStack placedItem, Block block) {
super(block);
this.placedItem = placedItem;
this.blockPlacer = blockPlacer;
}
/**
* This method returns the {@link BlockPlacer}
*
* @return The {@link BlockPlacer}
*/
public Block getBlockPlacer() {
return blockPlacer;
}
/**
* This returns the placed {@link ItemStack}.
*
* @return The placed {@link ItemStack}
*/
public ItemStack getItemStack() {
return placedItem;
}
/**
* This sets the placed {@link ItemStack}.
*
* @param item
* The {@link ItemStack} to be placed
*/
public void setItemStack(ItemStack item) {
Validate.notNull(item, "The ItemStack must not be null!");
if (!locked) {
this.placedItem = item;
}
else {
SlimefunItem.getByItem(placedItem).warn("A BlockPlacerPlaceEvent cannot be modified from within a BlockPlaceHandler!");
}
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
if (!locked) {
cancelled = cancel;
}
else {
SlimefunItem.getByItem(placedItem).warn("A BlockPlacerPlaceEvent cannot be modified from within a BlockPlaceHandler!");
}
}
/**
* This marks this {@link Event} as immutable, it can no longer be modified afterwards.
*/
public void setImmutable() {
locked = true;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
}

View File

@ -129,12 +129,13 @@ public class GEOResourceGenerationEvent extends Event {
return biome;
}
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
}

View File

@ -25,14 +25,6 @@ public class MultiBlockInteractEvent extends PlayerEvent implements Cancellable
private final BlockFace clickedFace;
private boolean cancelled;
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
public MultiBlockInteractEvent(Player p, MultiBlock mb, Block clicked, BlockFace face) {
super(p);
this.multiBlock = mb;
@ -77,4 +69,13 @@ public class MultiBlockInteractEvent extends PlayerEvent implements Cancellable
this.cancelled = cancel;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
}

View File

@ -30,14 +30,6 @@ public class PlayerLanguageChangeEvent extends Event {
this.to = to;
}
public static HandlerList getHandlerList() {
return handlers;
}
public HandlerList getHandlers() {
return handlers;
}
/**
* Returns the {@link Player} who triggered this {@link Event},
* the {@link Player} who switched his {@link Language} to be precise.
@ -66,4 +58,13 @@ public class PlayerLanguageChangeEvent extends Event {
return to;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
}

View File

@ -50,14 +50,6 @@ public class PlayerRightClickEvent extends Event {
}
}
public static HandlerList getHandlerList() {
return handlers;
}
public HandlerList getHandlers() {
return handlers;
}
public PlayerInteractEvent getInteractEvent() {
return event;
}
@ -144,4 +136,13 @@ public class PlayerRightClickEvent extends Event {
blockResult = result;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
}

View File

@ -47,12 +47,13 @@ public class ReactorExplodeEvent extends Event {
return reactor;
}
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
}

View File

@ -23,14 +23,6 @@ public class ResearchUnlockEvent extends Event implements Cancellable {
private final Research research;
private boolean cancelled;
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
public ResearchUnlockEvent(Player p, Research research) {
this.player = p;
this.research = research;
@ -54,4 +46,13 @@ public class ResearchUnlockEvent extends Event implements Cancellable {
this.cancelled = cancel;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
}

View File

@ -32,14 +32,6 @@ public class WaypointCreateEvent extends PlayerEvent implements Cancellable {
private final boolean deathpoint;
private boolean cancelled;
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
public WaypointCreateEvent(Player player, String name, Location location) {
super(player);
@ -112,4 +104,13 @@ public class WaypointCreateEvent extends PlayerEvent implements Cancellable {
this.cancelled = cancel;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public HandlerList getHandlers() {
return getHandlerList();
}
}

View File

@ -283,6 +283,14 @@ public class GPSNetwork {
if (!event.isCancelled()) {
String id = ChatColor.stripColor(ChatColors.color(event.getName())).toUpperCase(Locale.ROOT).replace(' ', '_');
for (Waypoint wp : profile.getWaypoints()) {
if (wp.getId().equals(id)) {
SlimefunPlugin.getLocalization().sendMessage(p, "gps.waypoint.duplicate", true, msg -> msg.replace("%waypoint%", event.getName()));
return;
}
}
profile.addWaypoint(new Waypoint(profile, id, event.getLocation(), event.getName()));
p.playSound(p.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 1F, 1F);

View File

@ -99,4 +99,9 @@ public final class HashedArmorpiece {
return item;
}
@Override
public String toString() {
return "HashedArmorpiece {hash=" + hash + ",item=" + item.map(SlimefunItem::getID).orElse(null) + '}';
}
}

View File

@ -225,6 +225,11 @@ public abstract class Network {
});
}
/**
* This returns the {@link Location} of the regulator block for this {@link Network}
*
* @return The {@link Location} of our regulator
*/
public Location getRegulator() {
return regulator;
}

View File

@ -32,8 +32,8 @@ import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.config.Config;
import io.github.thebusybiscuit.slimefun4.api.gps.Waypoint;
import io.github.thebusybiscuit.slimefun4.api.items.HashedArmorpiece;
import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectiveArmor;
import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectionType;
import io.github.thebusybiscuit.slimefun4.core.attributes.ProtectiveArmor;
import io.github.thebusybiscuit.slimefun4.core.guide.GuideHistory;
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
@ -455,11 +455,13 @@ public final class PlayerProfile {
int armorCount = 0;
NamespacedKey setId = null;
for (HashedArmorpiece armorpiece : armor) {
Optional<SlimefunArmorPiece> armorPiece = armorpiece.getItem();
if (!armorPiece.isPresent()) {
return false;
setId = null;
continue;
}
if (armorPiece.get() instanceof ProtectiveArmor) {

View File

@ -13,7 +13,9 @@ import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Piglin;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.collections.KeyMap;
@ -64,10 +66,12 @@ public class SlimefunRegistry {
private boolean enableResearches;
private boolean freeCreativeResearches;
private boolean researchFireworks;
private boolean logDuplicateBlockEntries;
private final Set<String> tickers = new HashSet<>();
private final Set<SlimefunItem> radioactive = new HashSet<>();
private final Set<String> activeChunks = new HashSet<>();
private final Set<String> activeChunks = ConcurrentHashMap.newKeySet();
private final Set<ItemStack> barterDrops = new HashSet<>();
private final KeyMap<GEOResource> geoResources = new KeyMap<>();
@ -82,7 +86,7 @@ public class SlimefunRegistry {
private final Map<Class<? extends ItemHandler>, Set<ItemHandler>> globalItemHandlers = new HashMap<>();
private final Map<String, SlimefunBlockHandler> blockHandlers = new HashMap<>();
private final Map<String, Set<Location>> activeTickers = new HashMap<>();
private final Map<String, Set<Location>> activeTickers = new ConcurrentHashMap<>();
private final Map<String, ItemStack> automatedCraftingChamberRecipes = new HashMap<>();
@ -98,6 +102,7 @@ public class SlimefunRegistry {
backwardsCompatibility = cfg.getBoolean("options.backwards-compatibility") || SlimefunPlugin.getMinecraftVersion().isBefore(MinecraftVersion.MINECRAFT_1_14);
freeCreativeResearches = cfg.getBoolean("researches.free-in-creative-mode");
researchFireworks = cfg.getBoolean("researches.enable-fireworks");
logDuplicateBlockEntries = cfg.getBoolean("options.log-duplicate-block-entries");
}
/**
@ -193,10 +198,26 @@ public class SlimefunRegistry {
return layouts.get(layout);
}
/**
* This returns a {@link Map} connecting the {@link EntityType} with a {@link Set}
* of {@link ItemStack ItemStacks} which would be dropped when an {@link Entity} of that type was killed.
*
* @return The {@link Map} of custom mob drops
*/
public Map<EntityType, Set<ItemStack>> getMobDrops() {
return mobDrops;
}
/**
* This returns a {@link Set} of {@link ItemStack ItemStacks} which can be obtained by bartering
* with {@link Piglin Piglins}.
*
* @return A {@link Set} of bartering drops
*/
public Set<ItemStack> getBarteringDrops() {
return barterDrops;
}
public Set<SlimefunItem> getRadioactiveItems() {
return radioactive;
}
@ -265,4 +286,8 @@ public class SlimefunRegistry {
return automatedCraftingChamberRecipes;
}
public boolean logDuplicateBlockEntries() {
return logDuplicateBlockEntries;
}
}

View File

@ -0,0 +1,36 @@
package io.github.thebusybiscuit.slimefun4.core.attributes;
import org.bukkit.entity.Piglin;
import org.bukkit.event.entity.EntityDropItemEvent;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.PiglinListener;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
/**
* This interface, when attached to a {@link SlimefunItem}, provides a variable (0-100%) chance for
* a {@link SlimefunItem} to be dropped by a {@link Piglin} on {@link EntityDropItemEvent}.
*
* @author dNiym
*
* @see PiglinListener
* @see RandomMobDrop
*
*/
@FunctionalInterface
public interface PiglinBarterDrop extends ItemAttribute {
/**
* Implement this method to make this {@link SlimefunItem} have a variable chance
* of being dropped by a {@link Piglin} when bartering with them. This interface
* should be used with the {@link RecipeType#BARTER_DROP}.
*
* It is recommended that this chance is kept reasonably low to feel like
* a vanilla drop as a 100% chance will completely override all {@link Piglin}
* barter drops. (NOTE: this feature only exists in 1.16+)
*
* @return The integer chance (1-99%) this {@link SlimefunItem} has to drop.
*/
int getBarteringLootChance();
}

View File

@ -37,18 +37,4 @@ public interface Placeable {
return false;
}
default void onPlace(Player p, Block b) {
// Override this as necessary
}
default boolean onBreak(Player p, Block b) {
// Override this as necessary
return true;
}
default boolean onExplode(Block b) {
// Override this as necessary
return true;
}
}

View File

@ -12,12 +12,13 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
/**
* This interface, when attached to a {@link SlimefunItem}, provides an easy method for adding
* a % chance to drop for an {@link SlimefunItem} on {@link EntityDeathEvent}, this chance is 0-100
* and used in conjunction with the MOB_DROP {@link RecipeType}.
* and used in conjunction with the {@link RecipeType#MOB_DROP}.
*
* @author dNiym
*
* @see BasicCircuitBoard
* @see MobDropListener
* @see PiglinBarterDrop
*
*/
@FunctionalInterface
@ -25,8 +26,8 @@ public interface RandomMobDrop extends ItemAttribute {
/**
* Implement this method to make the object have a variable chance of being
* added to the dropList when {@link EntityType} (specified in the recipe)
* is killed by the {@link Player}
* added to the dropList when {@link EntityType} specified in
* the {@link RecipeType#MOB_DROP} is killed by the {@link Player}.
*
* @return The integer chance (0-100%) {@link SlimefunItem} has to drop.
*/

View File

@ -4,6 +4,7 @@ import java.util.Map;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.HelpCommand;
import org.bukkit.entity.Player;
import io.github.thebusybiscuit.slimefun4.core.services.localization.Language;
@ -23,14 +24,35 @@ public abstract class SubCommand {
protected final SlimefunPlugin plugin;
protected final SlimefunCommand cmd;
protected SubCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
private final String name;
private final boolean hidden;
protected SubCommand(SlimefunPlugin plugin, SlimefunCommand cmd, String name, boolean hidden) {
this.plugin = plugin;
this.cmd = cmd;
this.name = name;
this.hidden = hidden;
}
public abstract String getName();
/**
* This returns the name of this {@link SubCommand}, the name is equivalent to the
* first argument given to the actual command.
*
* @return The name of this {@link SubCommand}
*/
public final String getName() {
return name;
}
public abstract boolean isHidden();
/**
* This method returns whether this {@link SubCommand} is hidden from the {@link HelpCommand}.
*
* @return Whether to hide this {@link SubCommand}
*/
public final boolean isHidden() {
return hidden;
}
protected void recordUsage(Map<SubCommand, Integer> commandUsage) {
commandUsage.merge(this, 1, Integer::sum);

View File

@ -17,12 +17,7 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
class BackpackCommand extends SubCommand {
BackpackCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd);
}
@Override
public String getName() {
return "backpack";
super(plugin, cmd, "backpack", false);
}
@Override
@ -30,11 +25,6 @@ class BackpackCommand extends SubCommand {
return "commands.backpack.description";
}
@Override
public boolean isHidden() {
return false;
}
@Override
public void onExecute(CommandSender sender, String[] args) {
if (!(sender instanceof Player) || !sender.hasPermission("slimefun.command.backpack")) {

View File

@ -11,17 +11,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class CheatCommand extends SubCommand {
CheatCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd);
}
@Override
public String getName() {
return "cheat";
}
@Override
public boolean isHidden() {
return false;
super(plugin, cmd, "cheat", false);
}
@Override

View File

@ -11,23 +11,13 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class DebugFishCommand extends SubCommand {
DebugFishCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd);
}
@Override
public String getName() {
return "debug_fish";
}
@Override
public boolean isHidden() {
return true;
super(plugin, cmd, "debug_fish", true);
}
@Override
public void onExecute(CommandSender sender, String[] args) {
if (sender instanceof Player && sender.isOp()) {
((Player) sender).getInventory().addItem(SlimefunItems.DEBUG_FISH);
if (sender instanceof Player && sender.hasPermission("slimefun.debugging")) {
((Player) sender).getInventory().addItem(SlimefunItems.DEBUG_FISH.clone());
}
else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true);

View File

@ -22,17 +22,7 @@ class GiveCommand extends SubCommand {
private static final String PLACEHOLDER_AMOUNT = "%amount%";
GiveCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd);
}
@Override
public String getName() {
return "give";
}
@Override
public boolean isHidden() {
return false;
super(plugin, cmd, "give", false);
}
@Override

View File

@ -12,24 +12,15 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class GuideCommand extends SubCommand {
GuideCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd);
}
@Override
public String getName() {
return "guide";
}
@Override
public boolean isHidden() {
return false;
super(plugin, cmd, "guide", false);
}
@Override
public void onExecute(CommandSender sender, String[] args) {
if (sender instanceof Player) {
if (sender.hasPermission("slimefun.command.guide")) {
((Player) sender).getInventory().addItem(SlimefunGuide.getItem(SlimefunPlugin.getCfg().getBoolean("guide.default-view-book") ? SlimefunGuideLayout.BOOK : SlimefunGuideLayout.CHEST));
SlimefunGuideLayout design = SlimefunGuide.getDefaultLayout();
((Player) sender).getInventory().addItem(SlimefunGuide.getItem(design).clone());
}
else {
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.no-permission", true);

View File

@ -9,17 +9,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class HelpCommand extends SubCommand {
HelpCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd);
}
@Override
public String getName() {
return "help";
}
@Override
public boolean isHidden() {
return false;
super(plugin, cmd, "help", false);
}
@Override

View File

@ -12,17 +12,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class OpenGuideCommand extends SubCommand {
OpenGuideCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd);
}
@Override
public String getName() {
return "open_guide";
}
@Override
public boolean isHidden() {
return false;
super(plugin, cmd, "open_guide", false);
}
@Override

View File

@ -19,17 +19,7 @@ class ResearchCommand extends SubCommand {
private static final String PLACEHOLDER_RESEARCH = "%research%";
ResearchCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd);
}
@Override
public String getName() {
return "research";
}
@Override
public boolean isHidden() {
return false;
super(plugin, cmd, "research", false);
}
@Override

View File

@ -14,17 +14,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class SearchCommand extends SubCommand {
SearchCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd);
}
@Override
public String getName() {
return "search";
}
@Override
public boolean isHidden() {
return false;
super(plugin, cmd, "search", false);
}
@Override

View File

@ -15,17 +15,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class StatsCommand extends SubCommand {
StatsCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd);
}
@Override
public String getName() {
return "stats";
}
@Override
public boolean isHidden() {
return false;
super(plugin, cmd, "stats", false);
}
@Override

View File

@ -13,17 +13,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class TeleporterCommand extends SubCommand {
TeleporterCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd);
}
@Override
public String getName() {
return "teleporter";
}
@Override
public boolean isHidden() {
return false;
super(plugin, cmd, "teleporter", false);
}
@Override

View File

@ -10,17 +10,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class TimingsCommand extends SubCommand {
TimingsCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd);
}
@Override
public String getName() {
return "timings";
}
@Override
public boolean isHidden() {
return false;
super(plugin, cmd, "timings", false);
}
@Override

View File

@ -2,32 +2,23 @@ package io.github.thebusybiscuit.slimefun4.core.commands.subcommands;
import java.util.Collection;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.plugin.Plugin;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.reflection.ReflectionUtils;
import io.github.thebusybiscuit.slimefun4.core.commands.SlimefunCommand;
import io.github.thebusybiscuit.slimefun4.core.commands.SubCommand;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.plugin.Plugin;
import io.papermc.lib.PaperLib;
class VersionsCommand extends SubCommand {
VersionsCommand(SlimefunPlugin plugin, SlimefunCommand cmd) {
super(plugin, cmd);
}
@Override
public String getName() {
return "versions";
}
@Override
public boolean isHidden() {
return false;
super(plugin, cmd, "versions", false);
}
@Override
@ -36,29 +27,33 @@ class VersionsCommand extends SubCommand {
// After all these years... Spigot still displays as "CraftBukkit"
// so we will just fix this inconsistency for them :)
String serverSoftware = PaperLib.isSpigot() && !PaperLib.isPaper() ? "Spigot" : Bukkit.getName();
sender.sendMessage(ChatColor.GRAY + "This Server uses the following setup of Slimefun:");
sender.sendMessage(ChatColors.color("&a" + serverSoftware + " &2" + ReflectionUtils.getVersion()));
sender.sendMessage("");
sender.sendMessage(ChatColors.color("&aCS-CoreLib &2v" + SlimefunPlugin.getCSCoreLibVersion()));
sender.sendMessage(ChatColors.color("&aSlimefun &2v" + SlimefunPlugin.getVersion()));
if (SlimefunPlugin.getMetricsService().getVersion() != null)
sender.sendMessage(ChatColors.color("&aMetrics: &2#" + SlimefunPlugin.getMetricsService().getVersion() + ')'));
if (SlimefunPlugin.getMetricsService().getVersion() != null) {
sender.sendMessage(ChatColors.color("&aMetrics build: &2#" + SlimefunPlugin.getMetricsService().getVersion()));
}
if (SlimefunPlugin.getRegistry().isBackwardsCompatible()) {
sender.sendMessage(ChatColor.YELLOW + "Backwards compatibility enabled!");
sender.sendMessage(ChatColor.RED + "Backwards compatibility enabled!");
}
sender.sendMessage("");
Collection<Plugin> addons = SlimefunPlugin.getInstalledAddons();
sender.sendMessage(ChatColors.color("&7Installed Addons &8(" + addons.size() + ")"));
sender.sendMessage(ChatColors.color("&7Installed Addons: &8(" + addons.size() + ")"));
for (Plugin plugin : addons) {
String version = plugin.getDescription().getVersion();
if (Bukkit.getPluginManager().isPluginEnabled(plugin)) {
sender.sendMessage(ChatColors.color(" &a" + plugin.getName() + " &2v" + plugin.getDescription().getVersion()));
sender.sendMessage(ChatColor.GREEN + " " + plugin.getName() + ChatColor.DARK_GREEN + " v" + version);
}
else {
sender.sendMessage(ChatColors.color(" &c" + plugin.getName() + " &4v" + plugin.getDescription().getVersion()));
sender.sendMessage(ChatColor.RED + " " + plugin.getName() + ChatColor.DARK_RED + " v" + version);
}
}
}

View File

@ -1,16 +1,10 @@
package io.github.thebusybiscuit.slimefun4.core.guide;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.BookSlimefunGuide;
@ -36,31 +30,7 @@ public final class SlimefunGuide {
private SlimefunGuide() {}
public static ItemStack getItem(SlimefunGuideLayout design) {
ItemStack item = new ItemStack(Material.ENCHANTED_BOOK);
ItemMeta meta = item.getItemMeta();
List<String> lore = new LinkedList<>();
lore.addAll(Arrays.asList("", ChatColors.color("&eRight Click &8\u21E8 &7Browse Items"), ChatColors.color("&eShift + Right Click &8\u21E8 &7Open Settings / Credits")));
switch (design) {
case BOOK:
meta.setDisplayName(ChatColors.color("&aSlimefun Guide &7(Book GUI)"));
break;
case CHEAT_SHEET:
meta.setDisplayName(ChatColors.color("&cSlimefun Guide &4(Cheat Sheet)"));
lore.add(0, ChatColors.color("&4&lOnly openable by Admins"));
lore.add(0, "");
break;
case CHEST:
meta.setDisplayName(ChatColors.color("&aSlimefun Guide &7(Chest GUI)"));
break;
default:
return null;
}
meta.setLore(lore);
SlimefunPlugin.getItemTextureService().setTexture(meta, "SLIMEFUN_GUIDE");
item.setItemMeta(meta);
return item;
return SlimefunPlugin.getRegistry().getGuideLayout(design).getItem();
}
public static void openCheatMenu(Player p) {
@ -132,4 +102,13 @@ public final class SlimefunGuide {
public static boolean isGuideItem(ItemStack item) {
return SlimefunUtils.isItemSimilar(item, getItem(SlimefunGuideLayout.CHEST), true) || SlimefunUtils.isItemSimilar(item, getItem(SlimefunGuideLayout.BOOK), true) || SlimefunUtils.isItemSimilar(item, getItem(SlimefunGuideLayout.CHEAT_SHEET), true);
}
public static SlimefunGuideLayout getDefaultLayout() {
if (SlimefunPlugin.getCfg().getBoolean("guide.default-view-book")) {
return SlimefunGuideLayout.BOOK;
}
else {
return SlimefunGuideLayout.CHEST;
}
}
}

View File

@ -21,6 +21,12 @@ import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
/**
* This menu shows a list of every {@link Contributor} to this project.
*
* @author TheBusyBiscuit
*
*/
final class ContributorsMenu {
private ContributorsMenu() {}

View File

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

View File

@ -1,5 +1,7 @@
package io.github.thebusybiscuit.slimefun4.core.guide.options;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.bukkit.ChatColor;
@ -16,6 +18,7 @@ import io.github.thebusybiscuit.slimefun4.core.services.localization.Language;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
@ -37,7 +40,16 @@ class PlayerLanguageOption implements SlimefunGuideOption<String> {
Language language = SlimefunPlugin.getLocalization().getLanguage(p);
String languageName = language.isDefault() ? (SlimefunPlugin.getLocalization().getMessage(p, "languages.default") + ChatColor.DARK_GRAY + " (" + language.getName(p) + ")") : SlimefunPlugin.getLocalization().getMessage(p, "languages." + language.getId());
return Optional.of(new CustomItem(language.getItem(), "&7" + SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.selected-language") + " &a" + languageName, "", "&7You now have the option to change", "&7the language in which Slimefun", "&7will send you messages.", "&7Note that this only translates", "&7some messages, not items.", "&7&oThis feature is still being worked on", "", "&7\u21E8 &eClick to change your language"));
List<String> lore = new ArrayList<>();
lore.add("");
lore.add("&e&o" + SlimefunPlugin.getLocalization().getMessage(p, "guide.work-in-progress"));
lore.add("");
lore.addAll(SlimefunPlugin.getLocalization().getMessages(p, "guide.languages.description", msg -> msg.replace("%contributors%", String.valueOf(SlimefunPlugin.getGitHubService().getContributors().size()))));
lore.add("");
lore.add("&7\u21E8 &e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.change"));
ItemStack item = new CustomItem(language.getItem(), "&7" + SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.selected-language") + " &a" + languageName, lore.toArray(new String[0]));
return Optional.of(item);
}
else {
return Optional.empty();
@ -78,7 +90,7 @@ class PlayerLanguageOption implements SlimefunGuideOption<String> {
});
}
else if (i == 7) {
menu.addItem(7, new CustomItem(SlimefunUtils.getCustomHead("3edd20be93520949e6ce789dc4f43efaeb28c717ee6bfcbbe02780142f716"), SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.translations.name"), "", "&7\u21E8 &e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.translations.lore")), (pl, slot, item, action) -> {
menu.addItem(7, new CustomItem(SlimefunUtils.getCustomHead(HeadTexture.ADD_NEW_LANGUAGE.getTexture()), SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.translations.name"), "", "&7\u21E8 &e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.translations.lore")), (pl, slot, item, action) -> {
ChatUtils.sendURL(pl, "https://github.com/TheBusyBiscuit/Slimefun4/wiki/Translating-Slimefun");
pl.closeInventory();
return false;
@ -105,7 +117,7 @@ class PlayerLanguageOption implements SlimefunGuideOption<String> {
int slot = 10;
for (Language language : SlimefunPlugin.getLocalization().getLanguages()) {
menu.addItem(slot, new CustomItem(language.getItem(), ChatColor.GREEN + language.getName(p), "&b" + SlimefunPlugin.getLocalization().getProgress(language) + '%', "", "&7\u21E8 &e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.select")), (pl, i, item, action) -> {
menu.addItem(slot, new CustomItem(language.getItem(), ChatColor.GREEN + language.getName(p), "&b" + language.getTranslationProgress() + '%', "", "&7\u21E8 &e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.languages.select")), (pl, i, item, action) -> {
SlimefunPlugin.instance().getServer().getPluginManager().callEvent(new PlayerLanguageChangeEvent(pl, SlimefunPlugin.getLocalization().getLanguage(pl), language));
setSelectedOption(pl, guide, language.getId());

View File

@ -19,6 +19,11 @@ import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuide;
*/
public interface SlimefunGuideOption<T> extends Keyed {
/**
* This returns the {@link SlimefunAddon} which added this {@link SlimefunGuideOption}.
*
* @return The registering {@link SlimefunAddon}
*/
SlimefunAddon getAddon();
Optional<ItemStack> getDisplayItem(Player p, ItemStack guide);

View File

@ -5,6 +5,7 @@ import java.util.List;
import java.util.Optional;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
@ -73,14 +74,21 @@ public final class SlimefunGuideSettings {
return false;
});
menu.addItem(2, new CustomItem(SlimefunUtils.getCustomHead("e952d2b3f351a6b0487cc59db31bf5f2641133e5ba0006b18576e996a0293e52"), "&c" + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.credits"), "", "&7Contributors: &e" + SlimefunPlugin.getGitHubService().getContributors().size(), "", "&7Slimefun is an open-source project", "&7and maintained by a large community of people.", "&7Here you can see who helped shape the project.", "", "&7\u21E8 &eClick to see our contributors"), (pl, slot, action, item) -> {
List<String> contributorsLore = new ArrayList<>();
contributorsLore.add("");
contributorsLore.addAll(SlimefunPlugin.getLocalization().getMessages(p, "guide.credits.description", msg -> msg.replace("%contributors%", String.valueOf(SlimefunPlugin.getGitHubService().getContributors().size()))));
contributorsLore.add("");
contributorsLore.add("&7\u21E8 &e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.credits.open"));
menu.addItem(2, new CustomItem(SlimefunUtils.getCustomHead("e952d2b3f351a6b0487cc59db31bf5f2641133e5ba0006b18576e996a0293e52"), "&c" + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.credits"), contributorsLore.toArray(new String[0])), (pl, slot, action, item) -> {
ContributorsMenu.open(pl, 0);
return false;
});
menu.addItem(4, new CustomItem(Material.WRITABLE_BOOK, "&aSlimefun Version", "&7&o" + SlimefunPlugin.getLocalization().getMessage(p, "guide.tooltips.versions-notice"), "", "&fMinecraft Version: &a" + Bukkit.getBukkitVersion(), "&fSlimefun Version: &a" + SlimefunPlugin.getVersion(), "&fCS-CoreLib Version: &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(), "&fCS-CoreLib: &a" + SlimefunPlugin.getCSCoreLibVersion()), ChestMenuUtils.getEmptyClickHandler());
menu.addItem(6, new CustomItem(Material.COMPARATOR, "&e" + SlimefunPlugin.getLocalization().getMessage(p, "guide.title.source"), "", "&7Last Activity: &a" + NumberUtils.getElapsedTime(SlimefunPlugin.getGitHubService().getLastUpdate()) + " ago", "&7Forks: &e" + SlimefunPlugin.getGitHubService().getForks(), "&7Stars: &e" + SlimefunPlugin.getGitHubService().getStars(), "", "&7&oSlimefun 4 is a community project,", "&7&othe source code is available on GitHub", "&7&oand if you want to keep this Plugin alive,", "&7&othen please consider contributing to it", "", "&7\u21E8 &eClick to go to GitHub"));
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"));
menu.addMenuClickHandler(6, (pl, slot, item, action) -> {
pl.closeInventory();
ChatUtils.sendURL(pl, "https://github.com/TheBusyBiscuit/Slimefun4");
@ -110,7 +118,7 @@ public final class SlimefunGuideSettings {
menu.addItem(49, ChestMenuUtils.getBackground(), ChestMenuUtils.getEmptyClickHandler());
}
menu.addItem(51, new CustomItem(Material.TOTEM_OF_UNDYING, "&cSoon", "", "&7Something will be added here later..."), (pl, slot, item, action) -> {
menu.addItem(51, new CustomItem(Material.TOTEM_OF_UNDYING, ChatColor.RED + SlimefunPlugin.getLocalization().getMessage(p, "guide.work-in-progress")), (pl, slot, item, action) -> {
// Add something here
return false;
});

View File

@ -1,18 +1,62 @@
package io.github.thebusybiscuit.slimefun4.core.handlers;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.events.BlockPlacerPlaceEvent;
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.BlockPlacer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
@FunctionalInterface
public interface BlockPlaceHandler extends ItemHandler {
/**
* This {@link ItemHandler} is called whenever a {@link Block} was placed.
* This only listens to any {@link Block} of the same {@link SlimefunItem} this is assigned
* to.
*
* @author TheBusyBiscuit
*
*/
public abstract class BlockPlaceHandler implements ItemHandler {
boolean onBlockPlace(Player p, BlockPlaceEvent e, ItemStack item);
private final boolean allowBlockPlacers;
public BlockPlaceHandler(boolean allowBlockPlacers) {
this.allowBlockPlacers = allowBlockPlacers;
}
/**
* This method is called whenever a {@link Player} placed this {@link Block}.
*
* @param e
* The corresponding {@link BlockPlaceEvent}
*/
public abstract void onPlayerPlace(BlockPlaceEvent e);
/**
* This method is called whenever a {@link BlockPlacer} places this {@link Block}.
* You cannot cancel the {@link BlockPlacerPlaceEvent} from within this method!
* Override the method {@link #isBlockPlacerAllowed()} instead if you want to disallow the
* {@link BlockPlacer} from placing this {@link Block}.
*
* @param e
* The corresponding {@link BlockPlacerPlaceEvent}
*/
public void onBlockPlacerPlace(BlockPlacerPlaceEvent e) {
// This can be overridden, if necessary
}
/**
* This returns whether the {@link BlockPlacer} is allowed to place a {@link Block} of this type.
*
* @return Whether a {@link BlockPlacer} is allowed to place this
*/
public boolean isBlockPlacerAllowed() {
return allowBlockPlacers;
}
@Override
default Class<? extends ItemHandler> getIdentifier() {
public Class<? extends ItemHandler> getIdentifier() {
return BlockPlaceHandler.class;
}
}

View File

@ -3,10 +3,12 @@ package io.github.thebusybiscuit.slimefun4.core.handlers;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.EntityInteractionListener;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
@ -15,9 +17,9 @@ import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
*
* @author Linox
*
* @see EntityInteractionListener
* @see ItemHandler
* @see SimpleSlimefunItem
* @see PlayerInteractAtEntityEvent
*
*/
@FunctionalInterface
@ -27,16 +29,14 @@ public interface EntityInteractHandler extends ItemHandler {
* This function is triggered when a {@link Player} right clicks with the assigned {@link SlimefunItem}
* in his hand.
*
* @param p
* The {@link Player} that right clicked
* @param entity
* The {@link Entity} that was right clicked on
* @param e
* The {@link PlayerInteractAtEntityEvent} which was called
* @param item
* The {@link ItemStack} that was held and used while triggering
* @param offHand
* <code>true</code> if the {@link EquipmentSlot} is off hand
*/
void onInteract(Player p, Entity entity, ItemStack item, boolean offHand);
void onInteract(PlayerInteractEntityEvent e, ItemStack item, boolean offHand);
@Override
default Class<? extends ItemHandler> getIdentifier() {

View File

@ -104,7 +104,7 @@ public class RainbowTickHandler extends BlockTicker {
}
});
b.setBlockData(block);
b.setBlockData(block, false);
return;
}
}

View File

@ -0,0 +1,45 @@
package io.github.thebusybiscuit.slimefun4.core.handlers;
import java.util.List;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.inventory.ItemStack;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
/**
* This {@link ItemHandler} is called when a {@link Block} is broken with a {@link SlimefunItem}
* as its tool.
*
* @author TheBusyBiscuit
*
* @see BlockBreakHandler
*
*/
@FunctionalInterface
public interface ToolUseHandler extends ItemHandler {
/**
* This method is called whenever a {@link BlockBreakEvent} was fired when using this
* {@link SlimefunItem} to break a {@link Block}.
*
* @param e
* The {@link BlockBreakEvent}
* @param tool
* The tool that was used
* @param fortune
* The amount of bonus drops to be expected from the fortune {@link Enchantment}.
* @param drops
* The dropped items
*
*/
void onToolUse(BlockBreakEvent e, ItemStack tool, int fortune, List<ItemStack> drops);
@Override
default Class<? extends ItemHandler> getIdentifier() {
return ToolUseHandler.class;
}
}

View File

@ -175,7 +175,7 @@ public class CargoNet extends ChestTerminalNetwork {
display();
}
SlimefunPlugin.getProfiler().scheduleEntries(1 + inputNodes.size());
SlimefunPlugin.getProfiler().scheduleEntries((terminals.isEmpty() ? 1 : 2) + inputs.size());
CargoNetworkTask runnable = new CargoNetworkTask(this, inputs, outputs, chestTerminalInputs, chestTerminalOutputs);
Slimefun.runSync(runnable);

View File

@ -16,6 +16,7 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
@ -63,6 +64,7 @@ class CargoNetworkTask implements Runnable {
// All operations happen here: Everything gets iterated from the Input Nodes.
// (Apart from ChestTerminal Buses)
SlimefunItem inputNode = SlimefunItems.CARGO_INPUT_NODE.getItem();
for (Map.Entry<Location, Integer> entry : inputs.entrySet()) {
long nodeTimestamp = System.nanoTime();
Location input = entry.getKey();
@ -71,12 +73,13 @@ class CargoNetworkTask implements Runnable {
attachedBlock.ifPresent(block -> routeItems(input, block, entry.getValue(), outputs));
// This will prevent this timings from showing up for the Cargo Manager
timestamp += SlimefunPlugin.getProfiler().closeEntry(entry.getKey(), SlimefunItems.CARGO_INPUT_NODE.getItem(), nodeTimestamp);
timestamp += SlimefunPlugin.getProfiler().closeEntry(entry.getKey(), inputNode, nodeTimestamp);
}
// Chest Terminal Code
if (SlimefunPlugin.getThirdPartySupportService().isChestTerminalInstalled()) {
network.updateTerminals(chestTerminalInputs);
// This will deduct any CT timings and attribute them towards the actual terminal
timestamp += network.updateTerminals(chestTerminalInputs);
}
// Submit a timings report

View File

@ -409,18 +409,36 @@ final class CargoUtils {
}
private static boolean matchesFilterList(ItemStack item, BlockMenu menu, boolean respectLore, boolean defaultValue) {
ItemStackWrapper wrapper = null;
// Little performance optimization:
// First check if there is more than one item to compare, if so
// then we know we should create an ItemStackWrapper, otherwise it would
// be of no benefit to us and just be redundant
int itemsToCompare = 0;
for (int slot : FILTER_SLOTS) {
ItemStack stack = menu.getItemInSlot(slot);
if (stack != null) {
if (wrapper == null) {
// Only create this as needed to save performance
wrapper = new ItemStackWrapper(item);
}
if (stack != null && stack.getType() != Material.AIR) {
itemsToCompare++;
if (SlimefunUtils.isItemSimilar(stack, wrapper, respectLore, false)) {
if (itemsToCompare > 1) {
break;
}
}
}
// Check if there are event non-air items
if (itemsToCompare > 0) {
// Only create the Wrapper if its worth it
if (itemsToCompare > 1) {
// Create an itemStackWrapper to save performance
item = new ItemStackWrapper(item);
}
for (int slot : FILTER_SLOTS) {
ItemStack stack = menu.getItemInSlot(slot);
if (SlimefunUtils.isItemSimilar(stack, item, respectLore, false)) {
return !defaultValue;
}
}

View File

@ -274,37 +274,49 @@ abstract class ChestTerminalNetwork extends Network {
*
* @param providers
* A {@link Set} of providers to this {@link ChestTerminalNetwork}
*
* @return The time it took to compute this operation
*/
protected void updateTerminals(Set<Location> providers) {
protected long updateTerminals(Set<Location> providers) {
if (terminals.isEmpty()) {
// Performance improvement - We don't need to compute items for
// Cargo networks without any Chest Terminals
return;
return 0;
}
// Timings will be slightly inaccurate here but most often people are gonna
// use no more than one terminal anyway, so this might be fine
long timestamp = SlimefunPlugin.getProfiler().newEntry();
// Timings will be slightly inaccurate here but most often people are not
// gonna use no more than one terminal anyway, so this might be fine
long timestamp = System.nanoTime();
Location firstTerminal = null;
SlimefunItem item = SlimefunItem.getByID("CHEST_TERMINAL");
List<ItemStackAndInteger> items = findAvailableItems(providers);
for (Location l : terminals) {
BlockMenu terminal = BlockStorage.getInventory(l);
int page = Integer.parseInt(BlockStorage.getLocationInfo(l, "page"));
try {
for (Location l : terminals) {
BlockMenu terminal = BlockStorage.getInventory(l);
int page = Integer.parseInt(BlockStorage.getLocationInfo(l, "page"));
if (!items.isEmpty() && items.size() < (page - 1) * TERMINAL_SLOTS.length + 1) {
page = 1;
BlockStorage.addBlockInfo(l, "page", String.valueOf(1));
if (!items.isEmpty() && items.size() < (page - 1) * TERMINAL_SLOTS.length + 1) {
page = 1;
BlockStorage.addBlockInfo(l, "page", String.valueOf(1));
}
for (int i = 0; i < TERMINAL_SLOTS.length; i++) {
int slot = TERMINAL_SLOTS[i];
int index = i + (TERMINAL_SLOTS.length * (page - 1));
updateTerminal(l, terminal, slot, index, items);
}
if (firstTerminal == null) {
firstTerminal = l;
}
}
for (int i = 0; i < TERMINAL_SLOTS.length; i++) {
int slot = TERMINAL_SLOTS[i];
int index = i + (TERMINAL_SLOTS.length * (page - 1));
updateTerminal(l, terminal, slot, index, items);
}
SlimefunPlugin.getProfiler().closeEntry(l, item, timestamp);
}
catch (Exception | LinkageError x) {
item.error("An Exception was caused while trying to tick Chest terminals", x);
}
return SlimefunPlugin.getProfiler().closeEntry(firstTerminal, item, timestamp);
}
private void updateTerminal(Location l, BlockMenu terminal, int slot, int index, List<ItemStackAndInteger> items) {
@ -316,7 +328,7 @@ abstract class ChestTerminalNetwork extends Network {
ItemMeta im = stack.getItemMeta();
List<String> lore = new ArrayList<>();
lore.add("");
lore.add(ChatColors.color("&7Stored Items: &r" + DoubleHandler.getFancyDouble(item.getInt())));
lore.add(ChatColors.color("&7Stored Items: &f" + DoubleHandler.getFancyDouble(item.getInt())));
if (stack.getMaxStackSize() > 1) {
int amount = item.getInt() > stack.getMaxStackSize() ? stack.getMaxStackSize() : item.getInt();
@ -437,7 +449,7 @@ abstract class ChestTerminalNetwork extends Network {
boolean add = true;
for (ItemStackAndInteger item : items) {
if (SlimefunUtils.isItemSimilar(stack, item.getItemStackWrapper(), true)) {
if (SlimefunUtils.isItemSimilar(stack, item.getItemStackWrapper(), true, false)) {
add = false;
item.add(stack.getAmount());
}

View File

@ -20,11 +20,9 @@ import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetProvider;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.reactors.Reactor;
import io.github.thebusybiscuit.slimefun4.utils.holograms.SimpleHologram;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.handlers.GeneratorTicker;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
@ -258,48 +256,6 @@ public class EnergyNet extends Network {
long time = SlimefunPlugin.getProfiler().closeEntry(source, item, timestamp);
timeCallback.accept(time);
}
else if (item != null) {
try {
// This will be removed very very soon
// It is only here for temporary backwards compatibility
GeneratorTicker generator = item.getEnergyTicker();
Integer capacity = SlimefunPlugin.getRegistry().getEnergyCapacities().get(item.getID());
if (capacity != null && capacity.intValue() > 0) {
generatorsWithCapacity.put(source, capacity);
}
if (generator != null) {
double energy = generator.generateEnergy(source, item, config);
if (generator.explode(source)) {
exploded.add(source);
BlockStorage.clearBlockInfo(source);
Reactor.processing.remove(source);
Reactor.progress.remove(source);
Slimefun.runSync(() -> {
source.getBlock().setType(Material.LAVA);
source.getWorld().createExplosion(source, 0F, false);
});
}
else {
supply += energy;
}
}
else {
item.warn("This Item was marked as a 'GENERATOR' but has no 'GeneratorTicker' attached to it! This must be fixed.");
}
}
catch (Exception | LinkageError t) {
exploded.add(source);
new ErrorReport(t, source, item);
}
long time = SlimefunPlugin.getProfiler().closeEntry(source, item, timestamp);
timeCallback.accept(time);
}
else {
// This block seems to be gone now, better remove it to be extra safe
exploded.add(source);

View File

@ -64,7 +64,7 @@ public class AutoSavingService {
}
if (players > 0) {
Slimefun.getLogger().log(Level.INFO, "Auto-Saved Player Data for {0} Player(s)!", players);
Slimefun.getLogger().log(Level.INFO, "Auto-saved all player data for {0} player(s)!", players);
}
}
@ -86,12 +86,14 @@ public class AutoSavingService {
}
if (!worlds.isEmpty()) {
Slimefun.getLogger().log(Level.INFO, "Auto-Saving Block Data... (Next Auto-Save: {0}m)", interval);
Slimefun.getLogger().log(Level.INFO, "Auto-saving block data... (Next auto-save: {0}m)", interval);
for (BlockStorage storage : worlds) {
storage.save(false);
storage.save();
}
}
BlockStorage.saveChunks();
}
}

View File

@ -37,7 +37,7 @@ public class BackupService implements Runnable {
if (backups.size() > MAX_BACKUPS) {
try {
deleteOldBackups(backups);
purgeBackups(backups);
}
catch (IOException e) {
Slimefun.getLogger().log(Level.WARNING, "Could not delete an old backup", e);
@ -112,7 +112,16 @@ public class BackupService implements Runnable {
}
}
private void deleteOldBackups(List<File> backups) throws IOException {
/**
* This method will delete old backups.
*
* @param backups
* The {@link List} of all backups
*
* @throws IOException
* An {@link IOException} is thrown if a {@link File} could not be deleted
*/
private void purgeBackups(List<File> backups) throws IOException {
Collections.sort(backups, (a, b) -> {
LocalDateTime time1 = LocalDateTime.parse(a.getName().substring(0, a.getName().length() - 4), format);
LocalDateTime time2 = LocalDateTime.parse(b.getName().substring(0, b.getName().length() - 4), format);

View File

@ -5,11 +5,14 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.logging.Level;
import org.apache.commons.lang.Validate;
import org.bukkit.NamespacedKey;
import org.bukkit.Server;
import org.bukkit.configuration.file.FileConfiguration;
@ -52,14 +55,17 @@ public class LocalizationService extends SlimefunLocalization implements Persist
if (serverDefaultLanguage != null) {
translationsEnabled = SlimefunPlugin.getCfg().getBoolean("options.enable-translations");
defaultLanguage = new Language(serverDefaultLanguage, "11b3188fd44902f72602bd7c2141f5a70673a411adb3d81862c69e536166b");
defaultLanguage.setMessagesFile(getConfig().getConfiguration());
loadEmbeddedLanguages();
String language = getConfig().getString(LANGUAGE_PATH);
if (language == null) language = serverDefaultLanguage;
if (language == null) {
language = serverDefaultLanguage;
}
if (hasLanguage(serverDefaultLanguage)) {
setLanguage(serverDefaultLanguage, !serverDefaultLanguage.equals(language));
@ -113,7 +119,16 @@ public class LocalizationService extends SlimefunLocalization implements Persist
return containsResource("messages_" + language);
}
/**
* This returns whether the given {@link Language} is loaded or not.
*
* @param id
* The id of that {@link Language}
*
* @return Whether or not this {@link Language} is loaded
*/
public boolean isLanguageLoaded(String id) {
Validate.notNull(id, "The language id cannot be null!");
return languages.containsKey(id);
}
@ -170,7 +185,10 @@ public class LocalizationService extends SlimefunLocalization implements Persist
}
@Override
protected void addLanguage(String id, String hash) {
protected void addLanguage(String id, String texture) {
Validate.notNull(id, "The language id cannot be null!");
Validate.notNull(texture, "The language texture cannot be null");
if (hasLanguage(id)) {
FileConfiguration messages = streamConfigFile("messages_" + id + ".yml", getConfig().getConfiguration());
FileConfiguration researches = streamConfigFile("researches_" + id + ".yml", null);
@ -178,7 +196,7 @@ public class LocalizationService extends SlimefunLocalization implements Persist
FileConfiguration categories = streamConfigFile("categories_" + id + ".yml", null);
FileConfiguration recipes = streamConfigFile("recipes_" + id + ".yml", null);
Language language = new Language(id, hash);
Language language = new Language(id, texture);
language.setMessagesFile(messages);
language.setResearchesFile(researches);
language.setResourcesFile(resources);
@ -199,25 +217,36 @@ public class LocalizationService extends SlimefunLocalization implements Persist
*
* @return A percentage {@code (0.0 - 100.0)} for the progress of translation of that {@link Language}
*/
public double getProgress(Language lang) {
int defaultKeys = getTotalKeys(languages.get("en"));
if (defaultKeys == 0) {
public double calculateProgress(Language lang) {
Validate.notNull(lang, "Cannot get the language progress of null");
Set<String> defaultKeys = getTotalKeys(languages.get("en"));
if (defaultKeys.isEmpty()) {
return 0;
}
return Math.min(DoubleHandler.fixDouble(100.0 * (getTotalKeys(lang) / (double) defaultKeys)), 100.0);
Set<String> keys = getTotalKeys(lang);
int matches = 0;
for (String key : defaultKeys) {
if (keys.contains(key)) {
matches++;
}
}
return Math.min(DoubleHandler.fixDouble(100.0 * (matches / (double) defaultKeys.size())), 100.0);
}
private int getTotalKeys(Language lang) {
private Set<String> getTotalKeys(Language lang) {
return getKeys(lang.getFiles());
}
private int getKeys(FileConfiguration... files) {
int keys = 0;
private Set<String> getKeys(FileConfiguration... files) {
Set<String> keys = new HashSet<>();
for (FileConfiguration cfg : files) {
keys += cfg != null ? cfg.getKeys(true).size() : 0;
keys.addAll(cfg.getKeys(true));
}
return keys;

View File

@ -13,6 +13,7 @@ import java.util.logging.Level;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
import kong.unirest.GetRequest;
import kong.unirest.HttpResponse;
import kong.unirest.JsonNode;
import kong.unirest.Unirest;
@ -31,9 +32,11 @@ import org.bukkit.plugin.Plugin;
*/
public class MetricsService {
private static final String API_URL = "https://api.github.com/";
private static final String REPO_NAME = "MetricsModule";
private static final String GH_API = "https://api.github.com/repos/Slimefun/" + REPO_NAME;
private static final String GH_RELEASES = "https://github.com/Slimefun/" + REPO_NAME + "/releases/download";
private static final String RELEASES_URL = API_URL + "repos/Slimefun/" + REPO_NAME + "/releases/latest";
private static final String DOWNLOAD_URL = "https://github.com/Slimefun/" + REPO_NAME + "/releases/download";
private final SlimefunPlugin plugin;
private final File parentFolder;
@ -79,38 +82,36 @@ public class MetricsService {
try {
// Load the jar file into a child class loader using the SF PluginClassLoader
// as a parent.
moduleClassLoader = URLClassLoader.newInstance(new URL[] { metricsModuleFile.toURI().toURL() },
plugin.getClass().getClassLoader());
Class<?> cl = moduleClassLoader.loadClass("dev.walshy.sfmetrics.MetricsModule");
moduleClassLoader = URLClassLoader.newInstance(new URL[] { metricsModuleFile.toURI().toURL() }, plugin.getClass().getClassLoader());
Class<?> metricsClass = moduleClassLoader.loadClass("dev.walshy.sfmetrics.MetricsModule");
metricVersion = cl.getPackage().getImplementationVersion();
metricVersion = metricsClass.getPackage().getImplementationVersion();
// If it has not been newly downloaded, auto-updates are on AND there's a new version
// then cleanup, download and start
if (!hasDownloadedUpdate && hasAutoUpdates() && checkForUpdate(metricVersion)
) {
plugin.getLogger().info("Cleaning up and re-loading Metrics.");
cleanUp();
if (!hasDownloadedUpdate && hasAutoUpdates() && checkForUpdate(metricVersion)) {
plugin.getLogger().info("Cleaned up, now re-loading Metrics-Module!");
start();
return;
}
// Finally, we're good to start this.
Method start = cl.getDeclaredMethod("start");
String version = cl.getPackage().getImplementationVersion();
Method start = metricsClass.getDeclaredMethod("start");
String version = metricsClass.getPackage().getImplementationVersion();
// This is required to be sync due to bStats.
Slimefun.runSync(() -> {
try {
start.invoke(null);
plugin.getLogger().info("Metrics build #" + version + " started.");
} catch (Exception e) {
}
catch (Exception | LinkageError e) {
plugin.getLogger().log(Level.WARNING, "Failed to start metrics.", e);
}
});
} catch (Exception e) {
plugin.getLogger().log(Level.WARNING,
"Failed to load the metrics module. Maybe the jar is corrupt?", e);
}
catch (Exception | LinkageError e) {
plugin.getLogger().log(Level.WARNING, "Failed to load the metrics module. Maybe the jar is corrupt?", e);
}
}
@ -120,12 +121,12 @@ public class MetricsService {
*/
public void cleanUp() {
try {
if (this.moduleClassLoader != null) {
this.moduleClassLoader.close();
if (moduleClassLoader != null) {
moduleClassLoader.close();
}
} catch (IOException e) {
plugin.getLogger().log(Level.WARNING,
"Could not clean up module class loader. Some memory may have been leaked.");
}
catch (IOException e) {
plugin.getLogger().log(Level.WARNING, "Could not clean up module class loader. Some memory may have been leaked.");
}
}
@ -133,7 +134,8 @@ public class MetricsService {
* Checks for a new update and compares it against the current version.
* If there is a new version available then this returns true.
*
* @param currentVersion The current version which is being used.
* @param currentVersion
* The current version which is being used.
* @return True if there is an update available.
*/
public boolean checkForUpdate(String currentVersion) {
@ -160,17 +162,22 @@ public class MetricsService {
*/
private int getLatestVersion() {
try {
HttpResponse<JsonNode> response = Unirest.get(GH_API + "/releases/latest")
.asJson();
if (!response.isSuccess()) return -1;
HttpResponse<JsonNode> response = Unirest.get(RELEASES_URL).asJson();
if (!response.isSuccess()) {
return -1;
}
JsonNode node = response.getBody();
if (node == null) return -1;
if (node == null) {
return -1;
}
return node.getObject().getInt("tag_name");
} catch (UnirestException e) {
plugin.getLogger().log(Level.SEVERE, "Failed to fetch latest builds for SFMetrics");
}
catch (UnirestException e) {
plugin.getLogger().log(Level.WARNING, "Failed to fetch latest builds for Metrics: {0}", e.getMessage());
return -1;
}
}
@ -178,49 +185,56 @@ public class MetricsService {
/**
* Downloads the version specified to Slimefun's data folder.
*
* @param version The version to download.
* @param version
* The version to download.
*/
private boolean download(int version) {
File f = new File(parentFolder, "Metrics-" + version + ".jar");
File file = new File(parentFolder, "Metrics-" + version + ".jar");
try {
plugin.getLogger().log(Level.INFO, "# Starting download of MetricsModule build: #{0}", version);
if (file.exists()) {
// Delete the file in case we accidentally downloaded it before
Files.delete(file.toPath());
}
AtomicInteger lastPercentPosted = new AtomicInteger();
HttpResponse<File> response = Unirest.get(GH_RELEASES + "/" + version
+ "/" + REPO_NAME + ".jar")
.downloadMonitor((b, fileName, bytesWritten, totalBytes) -> {
int percent = (int) (20 * (Math.round((((double) bytesWritten / totalBytes) * 100) / 20)));
GetRequest request = Unirest.get(DOWNLOAD_URL + "/" + version + "/" + REPO_NAME + ".jar");
HttpResponse<File> response = request.downloadMonitor((b, fileName, bytesWritten, totalBytes) -> {
int percent = (int) (20 * (Math.round((((double) bytesWritten / totalBytes) * 100) / 20)));
if (percent != 0 && percent != lastPercentPosted.get()) {
plugin.getLogger().info("# Downloading... " + percent + "% " + "(" + bytesWritten + "/" + totalBytes + " bytes)");
lastPercentPosted.set(percent);
}
}).asFile(file.getPath());
if (percent != 0 && percent != lastPercentPosted.get()) {
plugin.getLogger().info("# Downloading... " + percent + "% " +
"(" + bytesWritten + "/" + totalBytes + " bytes)");
lastPercentPosted.set(percent);
}
})
.asFile(f.getPath());
if (response.isSuccess()) {
plugin.getLogger().log(Level.INFO, "Successfully downloaded {0} build: #{1}", new Object[] {REPO_NAME, version});
plugin.getLogger().log(Level.INFO, "Successfully downloaded {0} build: #{1}", new Object[] { REPO_NAME, version });
// Replace the metric file with the new one
Files.move(f.toPath(), metricsModuleFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
cleanUp();
Files.move(file.toPath(), metricsModuleFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
metricVersion = String.valueOf(version);
hasDownloadedUpdate = true;
return true;
}
} catch (UnirestException e) {
plugin.getLogger().log(Level.WARNING, "Failed to fetch the latest jar file from the" +
" builds page. Perhaps GitHub is down.");
} catch (IOException e) {
plugin.getLogger().log(Level.WARNING, "Failed to replace the old metric file with the " +
"new one. Please do this manually! Error: {0}", e.getMessage());
}
catch (UnirestException e) {
plugin.getLogger().log(Level.WARNING, "Failed to fetch the latest jar file from the builds page. Perhaps GitHub is down?");
}
catch (IOException e) {
plugin.getLogger().log(Level.WARNING, "Failed to replace the old metric file with the new one. Please do this manually! Error: {0}", e.getMessage());
}
return false;
}
/**
* Returns the currently downloaded metrics version.
* Returns the currently downloaded metrics version.
* This <strong>can change</strong>! It may be null or an
* older version before it has downloaded a newer one.
*

View File

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

View File

@ -17,6 +17,8 @@ import kong.unirest.json.JSONException;
import me.mrCookieSlime.Slimefun.api.Slimefun;
abstract class GitHubConnector {
private static final String API_URL = "https://api.github.com/";
protected File file;
protected String repository;
@ -45,7 +47,7 @@ abstract class GitHubConnector {
}
try {
HttpResponse<JsonNode> resp = Unirest.get("https://api.github.com/repos/" + repository + getURLSuffix())
HttpResponse<JsonNode> resp = Unirest.get(API_URL + "repos/" + repository + getURLSuffix())
.header("User-Agent", "Slimefun4 (https://github.com/Slimefun)")
.asJson();
@ -54,7 +56,18 @@ abstract class GitHubConnector {
writeCacheFile(resp.getBody());
}
else {
Slimefun.getLogger().log(Level.WARNING, "Failed to fetch {0}", repository + getURLSuffix());
if (github.isLoggingEnabled()) {
Slimefun.getLogger().log(Level.WARNING, "Failed to fetch {0}: {1} - {2}", new Object[] {repository + getURLSuffix(), resp.getStatus(), resp.getBody()});
}
// It has the cached file, let's just read that then
if (file.exists()) {
JsonNode cache = readCacheFile();
if (cache != null) {
onSuccess(cache);
}
}
}
}
catch (UnirestException e) {
@ -78,21 +91,21 @@ abstract class GitHubConnector {
}
private JsonNode readCacheFile() {
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {
return new JsonNode(br.readLine());
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {
return new JsonNode(reader.readLine());
}
catch (IOException | JSONException e) {
Slimefun.getLogger().log(Level.WARNING, "Failed to read Github cache file: {0}", file.getName());
Slimefun.getLogger().log(Level.WARNING, "Failed to read Github cache file: {0} - {1}: {2}", new Object[] {file.getName(), e.getClass().getSimpleName(), e.getMessage()});
return null;
}
}
private void writeCacheFile(JsonNode node) {
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(node.toString().getBytes(StandardCharsets.UTF_8));
try (FileOutputStream output = new FileOutputStream(file)) {
output.write(node.toString().getBytes(StandardCharsets.UTF_8));
}
catch (IOException e) {
Slimefun.getLogger().log(Level.WARNING, "Failed to populate GitHub cache");
Slimefun.getLogger().log(Level.WARNING, "Failed to populate GitHub cache: {0} - {1}", new Object[] {e.getClass().getSimpleName(), e.getMessage()});
}
}
}

View File

@ -25,6 +25,7 @@ public final class Language {
private final String id;
private final ItemStack item;
private double progress = -1;
private FileConfiguration messages;
private FileConfiguration researches;
@ -60,6 +61,26 @@ public final class Language {
return id;
}
/**
* This method returns the progress of translation for this {@link Language}.
* The progress is determined by the amount of translated strings divided by the amount
* of strings in the english {@link Language} file and multiplied by 100.0
*
* @return A percentage {@code (0.0 - 100.0)} for the progress of translation of this {@link Language}
*/
public double getTranslationProgress() {
if (id.equals("en")) {
return 100.0;
}
else {
if (progress < 0) {
progress = SlimefunPlugin.getLocalization().calculateProgress(this);
}
return progress;
}
}
FileConfiguration getMessagesFile() {
return messages;
}
@ -145,7 +166,7 @@ public final class Language {
@Override
public String toString() {
return "Language [ id= " + id + " | default=" + isDefault() + " ]";
return "Language {id= " + id + ", default=" + isDefault() + " }";
}
public FileConfiguration[] getFiles() {

View File

@ -87,25 +87,62 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
public String getMessage(Player p, String key) {
Language language = getLanguage(p);
if (language == null) return "NO LANGUAGE FOUND";
return language.getMessagesFile().getString(key);
if (language == null) {
return "NO LANGUAGE FOUND";
}
String message = language.getMessagesFile().getString(key);
if (message == null) {
Language fallback = getLanguage(SupportedLanguage.ENGLISH.getLanguageId());
return fallback.getMessagesFile().getString(key);
}
return message;
}
public List<String> getMessages(Player p, String key) {
Language language = getLanguage(p);
if (language == null) return Arrays.asList("NO LANGUAGE FOUND");
return language.getMessagesFile().getStringList(key);
if (language == null) {
return Arrays.asList("NO LANGUAGE FOUND");
}
List<String> messages = language.getMessagesFile().getStringList(key);
if (messages.isEmpty()) {
Language fallback = getLanguage(SupportedLanguage.ENGLISH.getLanguageId());
return fallback.getMessagesFile().getStringList(key);
}
return messages;
}
public List<String> getMessages(Player p, String key, UnaryOperator<String> function) {
List<String> messages = getMessages(p, key);
messages.replaceAll(function);
return messages;
}
public String getResearchName(Player p, NamespacedKey key) {
Language language = getLanguage(p);
if (language.getResearchesFile() == null) return null;
if (language.getResearchesFile() == null) {
return null;
}
return language.getResearchesFile().getString(key.getNamespace() + "." + key.getKey());
}
public String getCategoryName(Player p, NamespacedKey key) {
Language language = getLanguage(p);
if (language.getCategoriesFile() == null) return null;
if (language.getCategoriesFile() == null) {
return null;
}
return language.getCategoriesFile().getString(key.getNamespace() + "." + key.getKey());
}
@ -118,7 +155,8 @@ public abstract class SlimefunLocalization extends Localization implements Keyed
return value;
}
else {
return getLanguage("en").getResourcesFile().getString(key);
Language fallback = getLanguage(SupportedLanguage.ENGLISH.getLanguageId());
return fallback.getResourcesFile().getString(key);
}
}

View File

@ -43,7 +43,7 @@ enum SupportedLanguage {
CHINESE_CHINA("zh-CN", true, "7f9bc035cdc80f1ab5e1198f29f3ad3fdd2b42d9a69aeb64de990681800b98dc"),
CHINESE_TAIWAN("zh-TW", true, "702a4afb2e1e2e3a1894a8b74272f95cfa994ce53907f9ac140bd3c932f9f"),
JAPANESE("ja", true, "d640ae466162a47d3ee33c4076df1cab96f11860f07edb1f0832c525a9e33323"),
KOREAN("ko", false, "fc1be5f12f45e413eda56f3de94e08d90ede8e339c7b1e8f32797390e9a5f"),
KOREAN("ko", true, "fc1be5f12f45e413eda56f3de94e08d90ede8e339c7b1e8f32797390e9a5f"),
HEBREW("he", false, "1ba086a2cc7272cf5ba49c80248546c22e5ef1bab54120e8a8e5d9e75b6a"),
ARABIC("ar", true, "a4be759a9cf7f0a19a7e8e62f23789ad1d21cebae38af9d9541676a3db001572"),
TURKISH("tr", true, "9852b9aba3482348514c1034d0affe73545c9de679ae4647f99562b5e5f47d09"),

View File

@ -38,6 +38,7 @@ public class Translators {
addTranslator("ThatsCube", SupportedLanguage.ITALIAN, true);
addTranslator("alessandrobasi", SupportedLanguage.ITALIAN, true);
addTranslator("dracrus", SupportedLanguage.ITALIAN, true);
addTranslator("prolletto64", SupportedLanguage.ITALIAN, true);
// Translators - Latvian
addTranslator("AgnisT", "NIKNAIZ", SupportedLanguage.LATVIAN, true);
@ -127,6 +128,7 @@ public class Translators {
addTranslator("yumjunstar", SupportedLanguage.KOREAN, true);
addTranslator("BlWon", SupportedLanguage.KOREAN, true);
addTranslator("20181241", SupportedLanguage.KOREAN, true);
addTranslator("kudansul", SupportedLanguage.KOREAN, true);
// Translators - Indonesian
addTranslator("diradho", SupportedLanguage.INDONESIAN, false);

View File

@ -14,9 +14,12 @@ import me.clip.placeholderapi.expansion.PlaceholderExpansion;
class PlaceholderAPIHook extends PlaceholderExpansion {
@Override
public String getAuthor() {
return SlimefunPlugin.instance().getDescription().getAuthors().toString();
private final String version;
private final String author;
public PlaceholderAPIHook(SlimefunPlugin plugin) {
this.version = plugin.getDescription().getVersion();
this.author = plugin.getDescription().getAuthors().toString();
}
@Override
@ -26,7 +29,12 @@ class PlaceholderAPIHook extends PlaceholderExpansion {
@Override
public String getVersion() {
return SlimefunPlugin.instance().getDescription().getVersion();
return version;
}
@Override
public String getAuthor() {
return author;
}
@Override

View File

@ -44,8 +44,17 @@ public class ThirdPartyPluginService {
public void start() {
if (isPluginInstalled("PlaceholderAPI")) {
isPlaceholderAPIInstalled = true;
new PlaceholderAPIHook().register();
try {
PlaceholderAPIHook hook = new PlaceholderAPIHook(plugin);
hook.register();
isPlaceholderAPIInstalled = true;
}
catch (Exception | LinkageError x) {
String version = plugin.getServer().getPluginManager().getPlugin("PlaceholderAPI").getDescription().getVersion();
Slimefun.getLogger().log(Level.WARNING, "Maybe consider updating PlaceholderAPI or Slimefun?");
Slimefun.getLogger().log(Level.WARNING, x, () -> "Failed to hook into PlaceholderAPI v" + version);
}
}
if (isPluginInstalled("EmeraldEnchants")) {

View File

@ -44,7 +44,7 @@ public class SlimefunProfiler {
// two ticks (sync and async blocks), so we use 100ms as a reference here
private static final int MAX_TICK_DURATION = 100;
private final ExecutorService executor = Executors.newFixedThreadPool(4);
private final ExecutorService executor = Executors.newFixedThreadPool(5);
private final AtomicBoolean running = new AtomicBoolean(false);
private final AtomicInteger queued = new AtomicInteger(0);
@ -118,7 +118,8 @@ public class SlimefunProfiler {
executor.execute(() -> {
ProfiledBlock block = new ProfiledBlock(l, item);
timings.putIfAbsent(block, elapsedTime);
// Merge (if we have multiple samples for whatever reason)
timings.merge(block, elapsedTime, Long::sum);
queued.decrementAndGet();
});
@ -143,7 +144,7 @@ public class SlimefunProfiler {
private void finishReport() {
// We will only wait for a maximum of this many 1ms sleeps
int iterations = 1000;
int iterations = 4000;
// Wait for all timing results to come in
while (!running.get() && queued.get() > 0) {
@ -153,6 +154,12 @@ public class SlimefunProfiler {
// If we waited for too long, then we should just abort
if (iterations <= 0) {
Iterator<CommandSender> iterator = requests.iterator();
while (iterator.hasNext()) {
iterator.next().sendMessage("Your timings report has timed out, we were still waiting for " + queued.get() + " samples to be collected :/");
iterator.remove();
}
return;
}
}

View File

@ -145,11 +145,11 @@ public final class SlimefunItems {
public static final SlimefunItemStack DIET_COOKIE = new SlimefunItemStack("DIET_COOKIE", Material.COOKIE, "&6Diet Cookie", "", "&aA very &olightweight &f&acookie.");
public static final SlimefunItemStack MAGIC_SUGAR = new SlimefunItemStack("MAGIC_SUGAR", Material.SUGAR, "&6Magic Sugar", "", "&a&oFeel the Power of Hermes!");
public static final SlimefunItemStack MONSTER_JERKY = new SlimefunItemStack("MONSTER_JERKY", Material.ROTTEN_FLESH, "&6Monster Jerky", "", "&a&oNo longer hungry");
public static final SlimefunItemStack APPLE_JUICE = new SlimefunItemStack("APPLE_JUICE", Color.RED, new PotionEffect(PotionEffectType.SATURATION, 6, 0), "&cApple Juice", "", "&7&oRestores &b&o" + "3.0" + " &7&oHunger");
public static final SlimefunItemStack MELON_JUICE = new SlimefunItemStack("MELON_JUICE", Color.RED, new PotionEffect(PotionEffectType.SATURATION, 6, 0), "&cMelon Juice", "", "&7&oRestores &b&o" + "3.0" + " &7&oHunger");
public static final SlimefunItemStack CARROT_JUICE = new SlimefunItemStack("CARROT_JUICE", Color.ORANGE, new PotionEffect(PotionEffectType.SATURATION, 6, 0), "&6Carrot Juice", "", "&7&oRestores &b&o" + "3.0" + " &7&oHunger");
public static final SlimefunItemStack PUMPKIN_JUICE = new SlimefunItemStack("PUMPKIN_JUICE", Color.ORANGE, new PotionEffect(PotionEffectType.SATURATION, 6, 0), "&6Pumpkin Juice", "", "&7&oRestores &b&o" + "3.0" + " &7&oHunger");
public static final SlimefunItemStack SWEET_BERRY_JUICE = new SlimefunItemStack("SWEET_BERRY_JUICE", Color.RED, new PotionEffect(PotionEffectType.SATURATION, 6, 0), "&cSweet Berry Juice", "", "&7&oRestores &b&o" + "3.0" + " &7&oHunger");
public static final SlimefunItemStack APPLE_JUICE = new SlimefunItemStack("APPLE_JUICE", Color.RED, new PotionEffect(PotionEffectType.SATURATION, 5, 0), "&cApple Juice", "", LoreBuilder.hunger(3));
public static final SlimefunItemStack MELON_JUICE = new SlimefunItemStack("MELON_JUICE", Color.RED, new PotionEffect(PotionEffectType.SATURATION, 5, 0), "&cMelon Juice", "", LoreBuilder.hunger(3));
public static final SlimefunItemStack CARROT_JUICE = new SlimefunItemStack("CARROT_JUICE", Color.ORANGE, new PotionEffect(PotionEffectType.SATURATION, 5, 0), "&6Carrot Juice", "", LoreBuilder.hunger(3));
public static final SlimefunItemStack PUMPKIN_JUICE = new SlimefunItemStack("PUMPKIN_JUICE", Color.ORANGE, new PotionEffect(PotionEffectType.SATURATION, 5, 0), "&6Pumpkin Juice", "", LoreBuilder.hunger(3));
public static final SlimefunItemStack SWEET_BERRY_JUICE = new SlimefunItemStack("SWEET_BERRY_JUICE", Color.RED, new PotionEffect(PotionEffectType.SATURATION, 5, 0), "&cSweet Berry Juice", "", LoreBuilder.hunger(3));
public static final SlimefunItemStack GOLDEN_APPLE_JUICE = new SlimefunItemStack("GOLDEN_APPLE_JUICE", Color.YELLOW, new PotionEffect(PotionEffectType.ABSORPTION, 20 * 20, 0), "&bGolden Apple Juice");
public static final SlimefunItemStack BEEF_JERKY = new SlimefunItemStack("BEEF_JERKY", Material.COOKED_BEEF, "&6Beef Jerky", "", "&fExtra saturating!");
@ -162,14 +162,14 @@ public final class SlimefunItems {
public static final SlimefunItemStack KELP_COOKIE = new SlimefunItemStack("KELP_COOKIE", Material.COOKIE, "&2Kelp Cookie");
/* Christmas */
public static final SlimefunItemStack CHRISTMAS_MILK = new SlimefunItemStack("CHRISTMAS_MILK", Color.WHITE, new PotionEffect(PotionEffectType.SATURATION, 5, 0), "&6Glass of Milk", "", "&7&oRestores &b&o" + "2.5" + " &7&oHunger");
public static final SlimefunItemStack CHRISTMAS_CHOCOLATE_MILK = new SlimefunItemStack("CHRISTMAS_CHOCOLATE_MILK", Color.MAROON, new PotionEffect(PotionEffectType.SATURATION, 12, 0), "&6Chocolate Milk", "", "&7&oRestores &b&o" + "6.0" + " &7&oHunger");
public static final SlimefunItemStack CHRISTMAS_EGG_NOG = new SlimefunItemStack("CHRISTMAS_EGG_NOG", Color.GRAY, new PotionEffect(PotionEffectType.SATURATION, 7, 0), "&aEgg Nog", "", "&7&oRestores &b&o" + "3.5" + " &7&oHunger");
public static final SlimefunItemStack CHRISTMAS_APPLE_CIDER = new SlimefunItemStack("CHRISTMAS_APPLE_CIDER", Color.RED, new PotionEffect(PotionEffectType.SATURATION, 14, 0), "&cApple Cider", "", "&7&oRestores &b&o" + "7.0" + " &7&oHunger");
public static final SlimefunItemStack CHRISTMAS_MILK = new SlimefunItemStack("CHRISTMAS_MILK", Color.WHITE, new PotionEffect(PotionEffectType.SATURATION, 4, 0), "&6Glass of Milk", "", LoreBuilder.hunger(2.5));
public static final SlimefunItemStack CHRISTMAS_CHOCOLATE_MILK = new SlimefunItemStack("CHRISTMAS_CHOCOLATE_MILK", Color.MAROON, new PotionEffect(PotionEffectType.SATURATION, 11, 0), "&6Chocolate Milk", "", LoreBuilder.hunger(6));
public static final SlimefunItemStack CHRISTMAS_EGG_NOG = new SlimefunItemStack("CHRISTMAS_EGG_NOG", Color.GRAY, new PotionEffect(PotionEffectType.SATURATION, 6, 0), "&aEgg Nog", "", LoreBuilder.hunger(3.5));
public static final SlimefunItemStack CHRISTMAS_APPLE_CIDER = new SlimefunItemStack("CHRISTMAS_APPLE_CIDER", Color.RED, new PotionEffect(PotionEffectType.SATURATION, 13, 0), "&cApple Cider", "", LoreBuilder.hunger(7));
public static final SlimefunItemStack CHRISTMAS_COOKIE = new SlimefunItemStack("CHRISTMAS_COOKIE", Material.COOKIE, ChatUtils.christmas("Christmas Cookie"));
public static final SlimefunItemStack CHRISTMAS_FRUIT_CAKE = new SlimefunItemStack("CHRISTMAS_FRUIT_CAKE", Material.PUMPKIN_PIE, ChatUtils.christmas("Fruit Cake"));
public static final SlimefunItemStack CHRISTMAS_APPLE_PIE = new SlimefunItemStack("CHRISTMAS_APPLE_PIE", Material.PUMPKIN_PIE, "&fApple Pie");
public static final SlimefunItemStack CHRISTMAS_HOT_CHOCOLATE = new SlimefunItemStack("CHRISTMAS_HOT_CHOCOLATE", Color.MAROON, new PotionEffect(PotionEffectType.SATURATION, 14, 0), "&6Hot Chocolate", "", "&7&oRestores &b&o" + "7.0" + " &7&oHunger");
public static final SlimefunItemStack CHRISTMAS_HOT_CHOCOLATE = new SlimefunItemStack("CHRISTMAS_HOT_CHOCOLATE", Color.MAROON, new PotionEffect(PotionEffectType.SATURATION, 13, 0), "&6Hot Chocolate", "", LoreBuilder.hunger(7));
public static final SlimefunItemStack CHRISTMAS_CAKE = new SlimefunItemStack("CHRISTMAS_CAKE", Material.PUMPKIN_PIE, ChatUtils.christmas("Christmas Cake"));
public static final SlimefunItemStack CHRISTMAS_CARAMEL = new SlimefunItemStack("CHRISTMAS_CARAMEL", Material.BRICK, "&6Caramel");
public static final SlimefunItemStack CHRISTMAS_CARAMEL_APPLE = new SlimefunItemStack("CHRISTMAS_CARAMEL_APPLE", Material.APPLE, "&6Caramel Apple");
@ -256,7 +256,7 @@ public final class SlimefunItems {
static {
hazmatLore.add("");
hazmatLore.add(ChatColor.GOLD + "Full set effects:");
hazmatLore.add(ChatColor.YELLOW + "- Radioation immunity");
hazmatLore.add(ChatColor.YELLOW + "- Radiation immunity");
if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_15)) {
hazmatLore.add(ChatColor.YELLOW + "- Bee Sting protection");
@ -287,10 +287,10 @@ public final class SlimefunItems {
public static final SlimefunItemStack GILDED_IRON_LEGGINGS = new SlimefunItemStack("GILDED_IRON_LEGGINGS", Material.GOLDEN_LEGGINGS, "&6Gilded Iron Leggings");
public static final SlimefunItemStack GILDED_IRON_BOOTS = new SlimefunItemStack("GILDED_IRON_BOOTS", Material.GOLDEN_BOOTS, "&6Gilded Iron Boots");
public static final SlimefunItemStack GOLD_HELMET = new SlimefunItemStack("GOLD_12K_HELMET", Material.GOLDEN_HELMET, "&6Gold Helmet", "&912-Carat");
public static final SlimefunItemStack GOLD_CHESTPLATE = new SlimefunItemStack("GOLD_12K_CHESTPLATE", Material.GOLDEN_CHESTPLATE, "&6Gold Chestplate", "&912-Carat");
public static final SlimefunItemStack GOLD_LEGGINGS = new SlimefunItemStack("GOLD_12K_LEGGINGS", Material.GOLDEN_LEGGINGS, "&6Gold Leggings", "&912-Carat");
public static final SlimefunItemStack GOLD_BOOTS = new SlimefunItemStack("GOLD_12K_BOOTS", Material.GOLDEN_BOOTS, "&6Gold Boots", "&912-Carat");
public static final SlimefunItemStack GOLDEN_HELMET_12K = new SlimefunItemStack("GOLD_12K_HELMET", Material.GOLDEN_HELMET, "&6Golden Helmet &7(12-Carat)");
public static final SlimefunItemStack GOLDEN_CHESTPLATE_12K = new SlimefunItemStack("GOLD_12K_CHESTPLATE", Material.GOLDEN_CHESTPLATE, "&6Golden Chestplate &7(12-Carat)");
public static final SlimefunItemStack GOLDEN_LEGGINGS_12K = new SlimefunItemStack("GOLD_12K_LEGGINGS", Material.GOLDEN_LEGGINGS, "&6Golden Leggings &7(12-Carat)");
public static final SlimefunItemStack GOLDEN_BOOTS_12K = new SlimefunItemStack("GOLD_12K_BOOTS", Material.GOLDEN_BOOTS, "&6Golden Boots &7(12-Carat)");
public static final SlimefunItemStack SLIME_HELMET_STEEL = new SlimefunItemStack("SLIME_STEEL_HELMET", Material.IRON_HELMET, "&a&lSlime Helmet", "&7&oReinforced", "", "&a&oBouncy Feeling");
public static final SlimefunItemStack SLIME_CHESTPLATE_STEEL = new SlimefunItemStack("SLIME_STEEL_CHESTPLATE", Material.IRON_CHESTPLATE, "&a&lSlime Chestplate", "&7&oReinforced", "", "&a&oBouncy Feeling");
@ -336,10 +336,10 @@ public final class SlimefunItems {
GILDED_IRON_LEGGINGS.addUnsafeEnchantments(gilded);
GILDED_IRON_BOOTS.addUnsafeEnchantments(gilded);
GOLD_HELMET.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLD_CHESTPLATE.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLD_LEGGINGS.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLD_BOOTS.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLDEN_HELMET_12K.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLDEN_CHESTPLATE_12K.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLDEN_LEGGINGS_12K.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
GOLDEN_BOOTS_12K.addUnsafeEnchantment(Enchantment.DURABILITY, 10);
Map<Enchantment, Integer> slime = new HashMap<>();
slime.put(Enchantment.DURABILITY, 4);
@ -409,12 +409,13 @@ public final class SlimefunItems {
public static final SlimefunItemStack ANCIENT_ALTAR = new SlimefunItemStack("ANCIENT_ALTAR", Material.ENCHANTING_TABLE, "&dAncient Altar", "", "&5Multi-Block Altar for", "&5magical Crafting Processes");
public static final SlimefunItemStack COPPER_WIRE = new SlimefunItemStack("COPPER_WIRE", Material.STRING, "&6Copper Wire", "", "&6Crucial component in electric modules");
public static final SlimefunItemStack RAINBOW_WOOL = new SlimefunItemStack("RAINBOW_WOOL", Material.WHITE_WOOL, "&5Rainbow Wool", "", "&dCycles through all Colors of the Rainbow!");
public static final SlimefunItemStack RAINBOW_GLASS = new SlimefunItemStack("RAINBOW_GLASS", Material.WHITE_STAINED_GLASS, "&5Rainbow Glass", "", "&dCycles through all Colors of the Rainbow!");
public static final SlimefunItemStack RAINBOW_CLAY = new SlimefunItemStack("RAINBOW_CLAY", Material.WHITE_TERRACOTTA, "&5Rainbow Clay", "", "&dCycles through all Colors of the Rainbow!");
public static final SlimefunItemStack RAINBOW_GLASS_PANE = new SlimefunItemStack("RAINBOW_GLASS_PANE", Material.WHITE_STAINED_GLASS_PANE, "&5Rainbow Glass Pane", "", "&dCycles through all Colors of the Rainbow!");
public static final SlimefunItemStack RAINBOW_CONCRETE = new SlimefunItemStack("RAINBOW_CONCRETE", Material.WHITE_CONCRETE, "&5Rainbow Concrete", "", "&dCycles through all Colors of the Rainbow!");
public static final SlimefunItemStack RAINBOW_GLAZED_TERRACOTTA = new SlimefunItemStack("RAINBOW_GLAZED_TERRACOTTA", Material.WHITE_GLAZED_TERRACOTTA, "&5Rainbow Glazed Terracotta", "", "&dCycles through all Colors of the Rainbow!");
private static final String RAINBOW = "&dCycles through all Colors of the Rainbow!";
public static final SlimefunItemStack RAINBOW_WOOL = new SlimefunItemStack("RAINBOW_WOOL", Material.WHITE_WOOL, "&5Rainbow Wool", "", RAINBOW);
public static final SlimefunItemStack RAINBOW_GLASS = new SlimefunItemStack("RAINBOW_GLASS", Material.WHITE_STAINED_GLASS, "&5Rainbow Glass", "", RAINBOW);
public static final SlimefunItemStack RAINBOW_CLAY = new SlimefunItemStack("RAINBOW_CLAY", Material.WHITE_TERRACOTTA, "&5Rainbow Clay", "", RAINBOW);
public static final SlimefunItemStack RAINBOW_GLASS_PANE = new SlimefunItemStack("RAINBOW_GLASS_PANE", Material.WHITE_STAINED_GLASS_PANE, "&5Rainbow Glass Pane", "", RAINBOW);
public static final SlimefunItemStack RAINBOW_CONCRETE = new SlimefunItemStack("RAINBOW_CONCRETE", Material.WHITE_CONCRETE, "&5Rainbow Concrete", "", RAINBOW);
public static final SlimefunItemStack RAINBOW_GLAZED_TERRACOTTA = new SlimefunItemStack("RAINBOW_GLAZED_TERRACOTTA", Material.WHITE_GLAZED_TERRACOTTA, "&5Rainbow Glazed Terracotta", "", RAINBOW);
/* Seasonal */
private static final String CHRISTMAS = ChatUtils.christmas("[Christmas Edition]");
@ -758,28 +759,28 @@ public final class SlimefunItems {
public static final SlimefunItemStack AUTO_BREEDER = new SlimefunItemStack("AUTO_BREEDER", Material.HAY_BLOCK, "&eAuto-Breeder", "", "&fRuns on &aOrganic Food", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), LoreBuilder.powerBuffer(1024), "&8\u21E8 &e\u26A1 &760 J/Animal");
public static final SlimefunItemStack ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD", HeadTexture.FILLED_CAN, "&aOrganic Food", "&7Content: &9???");
public static final SlimefunItemStack WHEAT_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_WHEAT", HeadTexture.FILLED_CAN, "&aOrganic Food", "&7Content: &9Wheat");
public static final SlimefunItemStack CARROT_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_CARROT", HeadTexture.FILLED_CAN, "&aOrganic Food", "&7Content: &9Carrots");
public static final SlimefunItemStack POTATO_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_POTATO", HeadTexture.FILLED_CAN, "&aOrganic Food", "&7Content: &9Potatoes");
public static final SlimefunItemStack SEEDS_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_SEEDS", HeadTexture.FILLED_CAN, "&aOrganic Food", "&7Content: &9Seeds");
public static final SlimefunItemStack BEETROOT_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_BEETROOT", HeadTexture.FILLED_CAN, "&aOrganic Food", "&7Content: &9Beetroot");
public static final SlimefunItemStack MELON_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_MELON", HeadTexture.FILLED_CAN, "&aOrganic Food", "&7Content: &9Melon");
public static final SlimefunItemStack APPLE_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_APPLE", HeadTexture.FILLED_CAN, "&aOrganic Food", "&7Content: &9Apple");
public static final SlimefunItemStack SWEET_BERRIES_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_SWEET_BERRIES", HeadTexture.FILLED_CAN, "&aOrganic Food", "&7Content: &9Sweet Berries");
public static final SlimefunItemStack KELP_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_KELP", HeadTexture.FILLED_CAN, "&aOrganic Food", "&7Content: &9Dried Kelp");
public static final SlimefunItemStack COCOA_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_COCOA", HeadTexture.FILLED_CAN, "&aOrganic Food", "&7Content: &9Cocoa Beans");
public static final SlimefunItemStack WHEAT_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_WHEAT", HeadTexture.FILLED_CAN, ORGANIC_FOOD.getDisplayName(), "&7Content: &9Wheat");
public static final SlimefunItemStack CARROT_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_CARROT", HeadTexture.FILLED_CAN, ORGANIC_FOOD.getDisplayName(), "&7Content: &9Carrots");
public static final SlimefunItemStack POTATO_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_POTATO", HeadTexture.FILLED_CAN, ORGANIC_FOOD.getDisplayName(), "&7Content: &9Potatoes");
public static final SlimefunItemStack SEEDS_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_SEEDS", HeadTexture.FILLED_CAN, ORGANIC_FOOD.getDisplayName(), "&7Content: &9Seeds");
public static final SlimefunItemStack BEETROOT_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_BEETROOT", HeadTexture.FILLED_CAN, ORGANIC_FOOD.getDisplayName(), "&7Content: &9Beetroot");
public static final SlimefunItemStack MELON_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_MELON", HeadTexture.FILLED_CAN, ORGANIC_FOOD.getDisplayName(), "&7Content: &9Melon");
public static final SlimefunItemStack APPLE_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_APPLE", HeadTexture.FILLED_CAN, ORGANIC_FOOD.getDisplayName(), "&7Content: &9Apple");
public static final SlimefunItemStack SWEET_BERRIES_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_SWEET_BERRIES", HeadTexture.FILLED_CAN, ORGANIC_FOOD.getDisplayName(), "&7Content: &9Sweet Berries");
public static final SlimefunItemStack KELP_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_KELP", HeadTexture.FILLED_CAN, ORGANIC_FOOD.getDisplayName(), "&7Content: &9Dried Kelp");
public static final SlimefunItemStack COCOA_ORGANIC_FOOD = new SlimefunItemStack("ORGANIC_FOOD_COCOA", HeadTexture.FILLED_CAN, ORGANIC_FOOD.getDisplayName(), "&7Content: &9Cocoa Beans");
public static final SlimefunItemStack FERTILIZER = new SlimefunItemStack("FERTILIZER", HeadTexture.FILLED_CAN, "&aOrganic Fertilizer", "&7Content: &9???");
public static final SlimefunItemStack WHEAT_FERTILIZER = new SlimefunItemStack("FERTILIZER_WHEAT", HeadTexture.FILLED_CAN, "&aOrganic Fertilizer", "&7Content: &9Wheat");
public static final SlimefunItemStack CARROT_FERTILIZER = new SlimefunItemStack("FERTILIZER_CARROT", HeadTexture.FILLED_CAN, "&aOrganic Fertilizer", "&7Content: &9Carrots");
public static final SlimefunItemStack POTATO_FERTILIZER = new SlimefunItemStack("FERTILIZER_POTATO", HeadTexture.FILLED_CAN, "&aOrganic Fertilizer", "&7Content: &9Potatoes");
public static final SlimefunItemStack SEEDS_FERTILIZER = new SlimefunItemStack("FERTILIZER_SEEDS", HeadTexture.FILLED_CAN, "&aOrganic Fertilizer", "&7Content: &9Seeds");
public static final SlimefunItemStack BEETROOT_FERTILIZER = new SlimefunItemStack("FERTILIZER_BEETROOT", HeadTexture.FILLED_CAN, "&aOrganic Fertilizer", "&7Content: &9Beetroot");
public static final SlimefunItemStack MELON_FERTILIZER = new SlimefunItemStack("FERTILIZER_MELON", HeadTexture.FILLED_CAN, "&aOrganic Fertilizer", "&7Content: &9Melon");
public static final SlimefunItemStack APPLE_FERTILIZER = new SlimefunItemStack("FERTILIZER_APPLE", HeadTexture.FILLED_CAN, "&aOrganic Fertilizer", "&7Content: &9Apple");
public static final SlimefunItemStack SWEET_BERRIES_FERTILIZER = new SlimefunItemStack("FERTILIZER_SWEET_BERRIES", HeadTexture.FILLED_CAN, "&aOrganic Fertilizer", "&7Content: &9Sweet Berries");
public static final SlimefunItemStack KELP_FERTILIZER = new SlimefunItemStack("FERTILIZER_KELP", HeadTexture.FILLED_CAN, "&aOrganic Fertilizer", "&7Content: &9Dried Kelp");
public static final SlimefunItemStack COCOA_FERTILIZER = new SlimefunItemStack("FERTILIZER_COCOA", HeadTexture.FILLED_CAN, "&aOrganic Fertilizer", "&7Content: &9Cocoa beans");
public static final SlimefunItemStack WHEAT_FERTILIZER = new SlimefunItemStack("FERTILIZER_WHEAT", HeadTexture.FILLED_CAN, FERTILIZER.getDisplayName(), "&7Content: &9Wheat");
public static final SlimefunItemStack CARROT_FERTILIZER = new SlimefunItemStack("FERTILIZER_CARROT", HeadTexture.FILLED_CAN, FERTILIZER.getDisplayName(), "&7Content: &9Carrots");
public static final SlimefunItemStack POTATO_FERTILIZER = new SlimefunItemStack("FERTILIZER_POTATO", HeadTexture.FILLED_CAN, FERTILIZER.getDisplayName(), "&7Content: &9Potatoes");
public static final SlimefunItemStack SEEDS_FERTILIZER = new SlimefunItemStack("FERTILIZER_SEEDS", HeadTexture.FILLED_CAN, FERTILIZER.getDisplayName(), "&7Content: &9Seeds");
public static final SlimefunItemStack BEETROOT_FERTILIZER = new SlimefunItemStack("FERTILIZER_BEETROOT", HeadTexture.FILLED_CAN, FERTILIZER.getDisplayName(), "&7Content: &9Beetroot");
public static final SlimefunItemStack MELON_FERTILIZER = new SlimefunItemStack("FERTILIZER_MELON", HeadTexture.FILLED_CAN, FERTILIZER.getDisplayName(), "&7Content: &9Melon");
public static final SlimefunItemStack APPLE_FERTILIZER = new SlimefunItemStack("FERTILIZER_APPLE", HeadTexture.FILLED_CAN, FERTILIZER.getDisplayName(), "&7Content: &9Apple");
public static final SlimefunItemStack SWEET_BERRIES_FERTILIZER = new SlimefunItemStack("FERTILIZER_SWEET_BERRIES", HeadTexture.FILLED_CAN, FERTILIZER.getDisplayName(), "&7Content: &9Sweet Berries");
public static final SlimefunItemStack KELP_FERTILIZER = new SlimefunItemStack("FERTILIZER_KELP", HeadTexture.FILLED_CAN, FERTILIZER.getDisplayName(), "&7Content: &9Dried Kelp");
public static final SlimefunItemStack COCOA_FERTILIZER = new SlimefunItemStack("FERTILIZER_COCOA", HeadTexture.FILLED_CAN, FERTILIZER.getDisplayName(), "&7Content: &9Cocoa beans");
public static final SlimefunItemStack ANIMAL_GROWTH_ACCELERATOR = new SlimefunItemStack("ANIMAL_GROWTH_ACCELERATOR", Material.HAY_BLOCK, "&bAnimal Growth Accelerator", "", "&fRuns on &aOrganic Food", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), LoreBuilder.powerBuffer(1024), LoreBuilder.powerPerSecond(28));
public static final SlimefunItemStack CROP_GROWTH_ACCELERATOR = new SlimefunItemStack("CROP_GROWTH_ACCELERATOR", Material.LIME_TERRACOTTA, "&aCrop Growth Accelerator", "", "&fRuns on &aOrganic Fertilizer", "", LoreBuilder.machine(MachineTier.END_GAME, MachineType.MACHINE), "&8\u21E8 &7Radius: 7x7", "&8\u21E8 &7Speed: &a3/time", LoreBuilder.powerBuffer(1024), LoreBuilder.powerPerSecond(50));

View File

@ -36,12 +36,12 @@ import io.github.thebusybiscuit.slimefun4.core.services.BlockDataService;
import io.github.thebusybiscuit.slimefun4.core.services.CustomItemDataService;
import io.github.thebusybiscuit.slimefun4.core.services.CustomTextureService;
import io.github.thebusybiscuit.slimefun4.core.services.LocalizationService;
import io.github.thebusybiscuit.slimefun4.core.services.MetricsService;
import io.github.thebusybiscuit.slimefun4.core.services.MinecraftRecipeService;
import io.github.thebusybiscuit.slimefun4.core.services.PerWorldSettingsService;
import io.github.thebusybiscuit.slimefun4.core.services.PermissionsService;
import io.github.thebusybiscuit.slimefun4.core.services.UpdaterService;
import io.github.thebusybiscuit.slimefun4.core.services.github.GitHubService;
import io.github.thebusybiscuit.slimefun4.core.services.MetricsService;
import io.github.thebusybiscuit.slimefun4.core.services.plugins.ThirdPartyPluginService;
import io.github.thebusybiscuit.slimefun4.core.services.profiler.SlimefunProfiler;
import io.github.thebusybiscuit.slimefun4.implementation.items.altar.AncientAltar;
@ -61,6 +61,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.DeathpointLis
import io.github.thebusybiscuit.slimefun4.implementation.listeners.DebugFishListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.DispenserListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.EnhancedFurnaceListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.EntityInteractionListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.ExplosionsListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.FireworksListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.GadgetsListener;
@ -69,7 +70,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.IronGolemList
import io.github.thebusybiscuit.slimefun4.implementation.listeners.ItemPickupListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.MobDropListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.MultiBlockListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.PlayerInteractEntityListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.PiglinListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.PlayerProfileListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SeismicAxeListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.SlimefunBootsListener;
@ -81,6 +82,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.listeners.SoulboundList
import io.github.thebusybiscuit.slimefun4.implementation.listeners.TalismanListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.VampireBladeListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.VanillaMachinesListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.VillagerTradingListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.WitherListener;
import io.github.thebusybiscuit.slimefun4.implementation.listeners.WorldListener;
import io.github.thebusybiscuit.slimefun4.implementation.resources.GEOResourcesSetup;
@ -110,6 +112,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
private static SlimefunPlugin instance;
private MinecraftVersion minecraftVersion = MinecraftVersion.UNKNOWN;
private boolean isNewlyInstalled = false;
private final SlimefunRegistry registry = new SlimefunRegistry();
private final TickerTask ticker = new TickerTask();
@ -163,10 +166,11 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
local = new LocalizationService(this, "", null);
gpsNetwork = new GPSNetwork();
command.register();
registry.load(config);
}
else if (getServer().getPluginManager().isPluginEnabled("CS-CoreLib")) {
long timestamp = System.nanoTime();
PaperLib.suggestPaper(this);
// We wanna ensure that the Server uses a compatible version of Minecraft
@ -175,6 +179,14 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
return;
}
// Disabling backwards-compatibility for fresh Slimefun installs
if (!new File("data-storage/Slimefun").exists()) {
config.setValue("options.backwards-compatibility", false);
config.save();
isNewlyInstalled = true;
}
// Creating all necessary Folders
getLogger().log(Level.INFO, "Creating directories...");
createDirectories();
@ -245,7 +257,8 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
// Armor Update Task
if (config.getBoolean("options.enable-armor-effects")) {
getServer().getScheduler().runTaskTimerAsynchronously(this, new ArmorTask(), 0L, config.getInt("options.armor-update-interval") * 20L);
boolean radioactiveFire = config.getBoolean("options.burn-players-when-radioactive");
getServer().getScheduler().runTaskTimerAsynchronously(this, new ArmorTask(radioactiveFire), 0L, config.getInt("options.armor-update-interval") * 20L);
}
autoSavingService.start(this, config.getInt("options.auto-save-delay-in-minutes"));
@ -354,7 +367,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
// Save all registered Worlds
for (Map.Entry<String, BlockStorage> entry : getRegistry().getWorlds().entrySet()) {
try {
entry.getValue().save(true);
entry.getValue().saveAndRemove();
}
catch (Exception x) {
getLogger().log(Level.SEVERE, x, () -> "An Error occurred while saving Slimefun-Blocks in World '" + entry.getKey() + "' for Slimefun " + getVersion());
@ -430,13 +443,17 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
new FireworksListener(this);
new WitherListener(this);
new IronGolemListener(this);
new PlayerInteractEntityListener(this);
new EntityInteractionListener(this);
new MobDropListener(this);
new VillagerTradingListener(this);
if (minecraftVersion.isAtLeast(MinecraftVersion.MINECRAFT_1_15)) {
new BeeListener(this);
}
new MobDropListener(this);
if (minecraftVersion.isAtLeast(MinecraftVersion.MINECRAFT_1_16)) {
new PiglinListener(this);
}
// Item-specific Listeners
new VampireBladeListener(this, (VampireBlade) SlimefunItems.BLADE_OF_VAMPIRES.getItem());
@ -488,6 +505,12 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
}
}
/**
* This returns the global instance of {@link SlimefunPlugin}.
* This may return null if the {@link Plugin} was disabled.
*
* @return The {@link SlimefunPlugin} instance
*/
public static SlimefunPlugin instance() {
return instance;
}
@ -637,6 +660,12 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
return instance.command;
}
/**
* This returns our instance of the {@link SlimefunProfiler}, a tool that is used
* to analyse performance and lag.
*
* @return The {@link SlimefunProfiler}
*/
public static SlimefunProfiler getProfiler() {
return instance.profiler;
}
@ -650,6 +679,16 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
return instance.minecraftVersion;
}
/**
* This method returns whether this version of Slimefun was newly installed.
* It will return true if this {@link Server} uses Slimefun for the very first time.
*
* @return Whether this is a new installation of Slimefun
*/
public static boolean isNewlyInstalled() {
return instance.isNewlyInstalled;
}
public static String getCSCoreLibVersion() {
return CSCoreLib.getLib().getDescription().getVersion();
}

View File

@ -10,6 +10,7 @@ import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.chat.ChatInput;
@ -18,7 +19,6 @@ import io.github.thebusybiscuit.cscorelib2.chat.json.ClickEvent;
import io.github.thebusybiscuit.cscorelib2.chat.json.CustomBookInterface;
import io.github.thebusybiscuit.cscorelib2.chat.json.HoverEvent;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.categories.FlexCategory;
import io.github.thebusybiscuit.slimefun4.core.categories.LockedCategory;
@ -36,6 +36,24 @@ import me.mrCookieSlime.Slimefun.api.Slimefun;
public class BookSlimefunGuide implements SlimefunGuideImplementation {
private final NamespacedKey guideSearch = new NamespacedKey(SlimefunPlugin.instance(), "search");
private final ItemStack item;
public BookSlimefunGuide() {
item = new ItemStack(Material.ENCHANTED_BOOK);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName(ChatColors.color("&aSlimefun Guide &7(Book GUI)"));
List<String> lore = new LinkedList<>();
lore.add("");
lore.add(ChatColors.color("&eRight Click &8\u21E8 &7Browse Items"));
lore.add(ChatColors.color("&eShift + Right Click &8\u21E8 &7Open Settings / Credits"));
meta.setLore(lore);
SlimefunPlugin.getItemTextureService().setTexture(meta, "SLIMEFUN_GUIDE");
item.setItemMeta(meta);
}
@Override
public SlimefunGuideLayout getLayout() {
@ -49,7 +67,7 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
@Override
public ItemStack getItem() {
return new CustomItem(new ItemStack(Material.ENCHANTED_BOOK), "&aSlimefun Guide &7(Book GUI)", "", "&eRight Click &8\u21E8 &7Browse Items", "&eShift + Right Click &8\u21E8 &7Open Settings / Credits");
return item;
}
private void openBook(Player p, PlayerProfile profile, List<ChatComponent> lines, boolean backButton) {
@ -112,37 +130,41 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
lines.add(new ChatComponent(ChatColor.DARK_GRAY + "\u21E8" + ChatColor.DARK_BLUE + " Tier " + tier + "\n"));
}
if (category instanceof LockedCategory && !((LockedCategory) category).hasUnlocked(p, profile)) {
List<String> lore = new LinkedList<>();
lore.add(ChatColor.DARK_RED + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked") + " " + ChatColor.GRAY + "- " + ChatColor.RESET + category.getItem(p).getItemMeta().getDisplayName());
lore.add("");
for (String line : SlimefunPlugin.getLocalization().getMessages(p, "guide.locked-category")) {
lore.add(ChatColor.RESET + line);
}
lore.add("");
for (Category parent : ((LockedCategory) category).getParents()) {
lore.add(parent.getItem(p).getItemMeta().getDisplayName());
}
ChatComponent chatComponent = new ChatComponent(ChatUtils.crop(ChatColor.RED, ItemUtils.getItemName(category.getItem(p))) + "\n");
chatComponent.setHoverEvent(new HoverEvent(lore));
lines.add(chatComponent);
}
else {
ChatComponent chatComponent = new ChatComponent(ChatUtils.crop(ChatColor.DARK_GREEN, ItemUtils.getItemName(category.getItem(p))) + "\n");
chatComponent.setHoverEvent(new HoverEvent(ItemUtils.getItemName(category.getItem(p)), "", ChatColor.GRAY + "\u21E8 " + ChatColor.GREEN + SlimefunPlugin.getLocalization().getMessage(p, "guide.tooltips.open-category")));
chatComponent.setClickEvent(new ClickEvent(category.getKey(), pl -> openCategory(profile, category, 1)));
lines.add(chatComponent);
}
addCategory(p, profile, category, lines);
}
}
openBook(p, profile, lines, false);
}
private void addCategory(Player p, PlayerProfile profile, Category category, List<ChatComponent> lines) {
if (category instanceof LockedCategory && !((LockedCategory) category).hasUnlocked(p, profile)) {
List<String> lore = new LinkedList<>();
lore.add(ChatColor.DARK_RED + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked") + " " + ChatColor.GRAY + "- " + ChatColor.RESET + category.getItem(p).getItemMeta().getDisplayName());
lore.add("");
for (String line : SlimefunPlugin.getLocalization().getMessages(p, "guide.locked-category")) {
lore.add(ChatColor.RESET + line);
}
lore.add("");
for (Category parent : ((LockedCategory) category).getParents()) {
lore.add(parent.getItem(p).getItemMeta().getDisplayName());
}
ChatComponent chatComponent = new ChatComponent(ChatUtils.crop(ChatColor.RED, ItemUtils.getItemName(category.getItem(p))) + "\n");
chatComponent.setHoverEvent(new HoverEvent(lore));
lines.add(chatComponent);
}
else {
ChatComponent chatComponent = new ChatComponent(ChatUtils.crop(ChatColor.DARK_GREEN, ItemUtils.getItemName(category.getItem(p))) + "\n");
chatComponent.setHoverEvent(new HoverEvent(ItemUtils.getItemName(category.getItem(p)), "", ChatColor.GRAY + "\u21E8 " + ChatColor.GREEN + SlimefunPlugin.getLocalization().getMessage(p, "guide.tooltips.open-category")));
chatComponent.setClickEvent(new ClickEvent(category.getKey(), pl -> openCategory(profile, category, 1)));
lines.add(chatComponent);
}
}
@Override
public void openCategory(PlayerProfile profile, Category category, int page) {
Player p = profile.getPlayer();
@ -159,20 +181,20 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
List<ChatComponent> items = new LinkedList<>();
for (SlimefunItem item : category.getItems()) {
if (Slimefun.hasPermission(p, item, false)) {
if (Slimefun.isEnabled(p, item, false)) {
appendSlimefunItem(category, page, p, profile, item, items);
for (SlimefunItem slimefunItem : category.getItems()) {
if (Slimefun.hasPermission(p, slimefunItem, false)) {
if (Slimefun.isEnabled(p, slimefunItem, false)) {
addSlimefunItem(category, page, p, profile, slimefunItem, items);
}
}
else {
ChatComponent component = new ChatComponent(ChatUtils.crop(ChatColor.DARK_RED, ItemUtils.getItemName(item.getItem())) + "\n");
ChatComponent component = new ChatComponent(ChatUtils.crop(ChatColor.DARK_RED, ItemUtils.getItemName(slimefunItem.getItem())) + "\n");
List<String> lore = new ArrayList<>();
lore.add(ChatColor.DARK_RED + ChatColor.stripColor(ItemUtils.getItemName(item.getItem())));
lore.add(ChatColor.DARK_RED + ChatColor.stripColor(ItemUtils.getItemName(slimefunItem.getItem())));
lore.add("");
for (String line : SlimefunPlugin.getPermissionsService().getLore(item)) {
for (String line : SlimefunPlugin.getPermissionsService().getLore(slimefunItem)) {
lore.add(ChatColors.color(line));
}
@ -188,7 +210,7 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
}
}
private void appendSlimefunItem(Category category, int page, Player p, PlayerProfile profile, SlimefunItem item, List<ChatComponent> items) {
private void addSlimefunItem(Category category, int page, Player p, PlayerProfile profile, SlimefunItem item, List<ChatComponent> items) {
NamespacedKey key = new NamespacedKey(SlimefunPlugin.instance(), item.getID().toLowerCase(Locale.ROOT));
if (!Slimefun.hasUnlocked(p, item, false) && item.getResearch() != null) {
@ -196,21 +218,7 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
ChatComponent component = new ChatComponent(ChatUtils.crop(ChatColor.RED, item.getItemName()) + "\n");
component.setHoverEvent(new HoverEvent(ChatColor.RESET + item.getItemName(), ChatColor.DARK_RED.toString() + ChatColor.BOLD + SlimefunPlugin.getLocalization().getMessage(p, "guide.locked"), "", ChatColor.GREEN + "> Click to unlock", "", ChatColor.GRAY + "Cost: " + ChatColor.AQUA.toString() + research.getCost() + " Level(s)"));
component.setClickEvent(new ClickEvent(key, player -> Slimefun.runSync(() -> {
if (!SlimefunPlugin.getRegistry().getCurrentlyResearchingPlayers().contains(p.getUniqueId())) {
if (research.canUnlock(p)) {
if (profile.hasUnlocked(research)) {
openCategory(profile, category, page);
}
else {
unlockItem(p, item, pl -> openCategory(profile, category, page));
}
}
else {
SlimefunPlugin.getLocalization().sendMessage(p, "messages.not-enough-xp", true);
}
}
})));
component.setClickEvent(new ClickEvent(key, player -> research(player, profile, item, research, category, page)));
items.add(component);
}
@ -230,6 +238,24 @@ public class BookSlimefunGuide implements SlimefunGuideImplementation {
}
}
private void research(Player p, PlayerProfile profile, SlimefunItem item, Research research, Category category, int page) {
Slimefun.runSync(() -> {
if (!SlimefunPlugin.getRegistry().getCurrentlyResearchingPlayers().contains(p.getUniqueId())) {
if (research.canUnlock(p)) {
if (profile.hasUnlocked(research)) {
openCategory(profile, category, page);
}
else {
unlockItem(p, item, pl -> openCategory(profile, category, page));
}
}
else {
SlimefunPlugin.getLocalization().sendMessage(p, "messages.not-enough-xp", true);
}
}
});
}
@Override
public void openSearch(PlayerProfile profile, String input, boolean addToHistory) {
// We need to write a book implementation for this at some point

View File

@ -1,16 +1,41 @@
package io.github.thebusybiscuit.slimefun4.implementation.guide;
import org.bukkit.entity.Player;
import java.util.LinkedList;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideLayout;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
public class CheatSheetSlimefunGuide extends ChestSlimefunGuide {
private final ItemStack item;
public CheatSheetSlimefunGuide() {
super(false);
item = new ItemStack(Material.ENCHANTED_BOOK);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName(ChatColors.color("&cSlimefun Guide &4(Cheat Sheet)"));
List<String> lore = new LinkedList<>();
lore.add(ChatColors.color("&4&lOnly openable by Admins"));
lore.add(ChatColors.color("&eRight Click &8\u21E8 &7Browse Items"));
lore.add(ChatColors.color("&eShift + Right Click &8\u21E8 &7Open Settings / Credits"));
meta.setLore(lore);
SlimefunPlugin.getItemTextureService().setTexture(meta, "SLIMEFUN_GUIDE");
item.setItemMeta(meta);
}
@Override
@ -23,6 +48,11 @@ public class CheatSheetSlimefunGuide extends ChestSlimefunGuide {
return SlimefunGuideLayout.CHEAT_SHEET;
}
@Override
public ItemStack getItem() {
return item;
}
@Override
protected void createHeader(Player p, PlayerProfile profile, ChestMenu menu) {
super.createHeader(p, profile, menu);

View File

@ -18,7 +18,9 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.Recipe;
import org.bukkit.inventory.RecipeChoice;
import org.bukkit.inventory.RecipeChoice.MaterialChoice;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.chat.ChatInput;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
@ -50,6 +52,7 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
private static final int CATEGORY_SIZE = 36;
private final ItemStack item;
private final int[] recipeSlots = { 3, 4, 5, 12, 13, 14, 21, 22, 23 };
private final Sound sound;
private final boolean showVanillaRecipes;
@ -63,6 +66,21 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
else {
sound = Sound.ENTITY_BAT_TAKEOFF;
}
item = new ItemStack(Material.ENCHANTED_BOOK);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName(ChatColors.color("&aSlimefun Guide &7(Chest GUI)"));
List<String> lore = new LinkedList<>();
lore.add("");
lore.add(ChatColors.color("&eRight Click &8\u21E8 &7Browse Items"));
lore.add(ChatColors.color("&eShift + Right Click &8\u21E8 &7Open Settings / Credits"));
meta.setLore(lore);
SlimefunPlugin.getItemTextureService().setTexture(meta, "SLIMEFUN_GUIDE");
item.setItemMeta(meta);
}
@Override
@ -72,7 +90,7 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
@Override
public ItemStack getItem() {
return new CustomItem(new ItemStack(Material.ENCHANTED_BOOK), "&aSlimefun Guide &7(Chest GUI)", "", "&eRight Click &8\u21E8 &7Browse Items", "&eShift + Right Click &8\u21E8 &7Open Settings / Credits");
return item;
}
@Override
@ -313,17 +331,17 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
int index = 9;
// Find items and add them
for (SlimefunItem item : SlimefunPlugin.getRegistry().getEnabledSlimefunItems()) {
String itemName = ChatColor.stripColor(item.getItemName()).toLowerCase(Locale.ROOT);
for (SlimefunItem slimefunItem : SlimefunPlugin.getRegistry().getEnabledSlimefunItems()) {
String itemName = ChatColor.stripColor(slimefunItem.getItemName()).toLowerCase(Locale.ROOT);
if (index == 44) {
break;
}
if (!itemName.isEmpty() && (itemName.equals(searchTerm) || itemName.contains(searchTerm))) {
ItemStack itemstack = new CustomItem(item.getItem(), meta -> {
ItemStack itemstack = new CustomItem(slimefunItem.getItem(), meta -> {
List<String> lore = null;
Category category = item.getCategory();
Category category = slimefunItem.getCategory();
if (category != null) {
ItemStack categoryItem = category.getItem(p);
@ -341,10 +359,10 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
menu.addMenuClickHandler(index, (pl, slot, itm, action) -> {
try {
if (!isSurvivalMode()) {
pl.getInventory().addItem(item.getItem().clone());
pl.getInventory().addItem(slimefunItem.getItem().clone());
}
else {
displayItem(profile, item, true);
displayItem(profile, slimefunItem, true);
}
}
catch (Exception | LinkageError x) {
@ -400,30 +418,9 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
RecipeChoiceTask task = new RecipeChoiceTask();
if (optional.isPresent()) {
MinecraftRecipe<?> mcRecipe = optional.get();
showRecipeChoices(recipe, recipeItems, task);
RecipeChoice[] choices = SlimefunPlugin.getMinecraftRecipeService().getRecipeShape(recipe);
if (choices.length == 1 && choices[0] instanceof MaterialChoice) {
recipeItems[4] = new ItemStack(((MaterialChoice) choices[0]).getChoices().get(0));
if (((MaterialChoice) choices[0]).getChoices().size() > 1) {
task.add(recipeSlots[4], (MaterialChoice) choices[0]);
}
}
else {
for (int i = 0; i < choices.length; i++) {
if (choices[i] instanceof MaterialChoice) {
recipeItems[i] = new ItemStack(((MaterialChoice) choices[i]).getChoices().get(0));
if (((MaterialChoice) choices[i]).getChoices().size() > 1) {
task.add(recipeSlots[i], (MaterialChoice) choices[i]);
}
}
}
}
recipeType = new RecipeType(mcRecipe);
recipeType = new RecipeType(optional.get());
result = recipe.getResult();
}
else {
@ -465,6 +462,29 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
}
}
private <T extends Recipe> void showRecipeChoices(T recipe, ItemStack[] recipeItems, RecipeChoiceTask task) {
RecipeChoice[] choices = SlimefunPlugin.getMinecraftRecipeService().getRecipeShape(recipe);
if (choices.length == 1 && choices[0] instanceof MaterialChoice) {
recipeItems[4] = new ItemStack(((MaterialChoice) choices[0]).getChoices().get(0));
if (((MaterialChoice) choices[0]).getChoices().size() > 1) {
task.add(recipeSlots[4], (MaterialChoice) choices[0]);
}
}
else {
for (int i = 0; i < choices.length; i++) {
if (choices[i] instanceof MaterialChoice) {
recipeItems[i] = new ItemStack(((MaterialChoice) choices[i]).getChoices().get(0));
if (((MaterialChoice) choices[i]).getChoices().size() > 1) {
task.add(recipeSlots[i], (MaterialChoice) choices[i]);
}
}
}
}
}
@Override
public void displayItem(PlayerProfile profile, SlimefunItem item, boolean addToHistory) {
Player p = profile.getPlayer();
@ -670,15 +690,15 @@ public class ChestSlimefunGuide implements SlimefunGuideImplementation {
private void addDisplayRecipe(ChestMenu menu, PlayerProfile profile, List<ItemStack> recipes, int slot, int i, int page) {
if ((i + (page * 18)) < recipes.size()) {
ItemStack item = recipes.get(i + (page * 18));
ItemStack displayItem = recipes.get(i + (page * 18));
// We want to clone this item to avoid corrupting the original
// but we wanna make sure no stupid addon creator sneaked some nulls in here
if (item != null) {
item = item.clone();
if (displayItem != null) {
displayItem = displayItem.clone();
}
menu.replaceExistingItem(slot, item);
menu.replaceExistingItem(slot, displayItem);
if (page == 0) {
menu.addMenuClickHandler(slot, (pl, s, itemstack, action) -> {

View File

@ -15,6 +15,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
* A quick and easy implementation of {@link SlimefunItem} that also implements the
* interface {@link Radioactive}.
* This implementation is {@link NotPlaceable}!
*
* Simply specify a level of {@link Radioactivity} in the constructor.
*
@ -43,10 +44,29 @@ public class RadioactiveItem extends SlimefunItem implements Radioactive, NotPla
* The recipe of how to craft this {@link SlimefunItem}
*/
public RadioactiveItem(Category category, Radioactivity radioactivity, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
this(category, radioactivity, item, recipeType, recipe, null);
}
/**
* This will create a new {@link RadioactiveItem} with the given level of {@link Radioactivity}
*
* @param category
* The {@link Category} of this {@link SlimefunItem}
* @param radioactivity
* the level of {@link Radioactivity}
* @param item
* the {@link SlimefunItemStack} this {@link SlimefunItem} represents
* @param recipeType
* The {@link RecipeType} for this item
* @param recipe
* The recipe of how to craft this {@link SlimefunItem}
* @param recipeOutput
* The recipe output
*/
public RadioactiveItem(Category category, Radioactivity radioactivity, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
super(category, item, recipeType, recipe, recipeOutput);
this.radioactivity = radioactivity;
addItemHandler(onRightClick());
}

View File

@ -16,17 +16,17 @@ public enum AndroidFuelSource {
/**
* This {@link ProgrammableAndroid} runs on solid fuel, e.g. Wood or coal
*/
SOLID("", "&rThis Android runs on solid Fuel", "&re.g. Coal, Wood, etc..."),
SOLID("", "&fThis Android runs on solid Fuel", "&fe.g. Coal, Wood, etc..."),
/**
* This {@link ProgrammableAndroid} runs on liquid fuel, e.g. Fuel, Oil or Lava
*/
LIQUID("", "&rThis Android runs on liquid Fuel", "&re.g. Lava, Oil, Fuel, etc..."),
LIQUID("", "&fThis Android runs on liquid Fuel", "&fe.g. Lava, Oil, Fuel, etc..."),
/**
* This {@link ProgrammableAndroid} runs on nuclear fuel, e.g. Uranium
*/
NUCLEAR("", "&rThis Android runs on radioactive Fuel", "&re.g. Uranium, Neptunium or Boosted Uranium");
NUCLEAR("", "&fThis Android runs on radioactive Fuel", "&fe.g. Uranium, Neptunium or Boosted Uranium");
private final String[] lore;

View File

@ -6,6 +6,7 @@ import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.inventory.ItemStack;
@ -39,24 +40,28 @@ public abstract class MinerAndroid extends ProgrammableAndroid {
protected void dig(Block b, BlockMenu menu, Block block) {
Collection<ItemStack> drops = block.getDrops(effectivePickaxe);
if (!MaterialCollections.getAllUnbreakableBlocks().contains(block.getType()) && !drops.isEmpty() && SlimefunPlugin.getProtectionManager().hasPermission(Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner"))), block.getLocation(), ProtectableAction.BREAK_BLOCK)) {
if (!MaterialCollections.getAllUnbreakableBlocks().contains(block.getType()) && !drops.isEmpty()) {
OfflinePlayer owner = Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner")));
AndroidMineEvent event = new AndroidMineEvent(block, new AndroidInstance(this, b));
Bukkit.getPluginManager().callEvent(event);
if (SlimefunPlugin.getProtectionManager().hasPermission(owner, block.getLocation(), ProtectableAction.BREAK_BLOCK)) {
AndroidMineEvent event = new AndroidMineEvent(block, new AndroidInstance(this, b));
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
if (event.isCancelled()) {
return;
}
// We only want to break non-Slimefun blocks
String blockId = BlockStorage.checkID(block);
if (blockId == null) {
for (ItemStack drop : drops) {
if (menu.fits(drop, getOutputSlots())) {
menu.pushItem(drop, getOutputSlots());
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType());
block.setType(Material.AIR);
// We only want to break non-Slimefun blocks
String blockId = BlockStorage.checkID(block);
if (blockId == null) {
for (ItemStack drop : drops) {
if (menu.fits(drop, getOutputSlots())) {
menu.pushItem(drop, getOutputSlots());
}
}
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType());
block.setType(Material.AIR);
}
}
}
@ -66,30 +71,34 @@ public abstract class MinerAndroid extends ProgrammableAndroid {
protected void moveAndDig(Block b, BlockMenu menu, BlockFace face, Block block) {
Collection<ItemStack> drops = block.getDrops(effectivePickaxe);
if (!MaterialCollections.getAllUnbreakableBlocks().contains(block.getType()) && !drops.isEmpty() && SlimefunPlugin.getProtectionManager().hasPermission(Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner"))), block.getLocation(), ProtectableAction.BREAK_BLOCK)) {
if (!MaterialCollections.getAllUnbreakableBlocks().contains(block.getType()) && !drops.isEmpty()) {
OfflinePlayer owner = Bukkit.getOfflinePlayer(UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner")));
AndroidMineEvent event = new AndroidMineEvent(block, new AndroidInstance(this, b));
Bukkit.getPluginManager().callEvent(event);
if (SlimefunPlugin.getProtectionManager().hasPermission(owner, block.getLocation(), ProtectableAction.BREAK_BLOCK)) {
AndroidMineEvent event = new AndroidMineEvent(block, new AndroidInstance(this, b));
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
// We only want to break non-Slimefun blocks
SlimefunItem blockId = BlockStorage.check(block);
if (blockId == null) {
for (ItemStack drop : drops) {
if (menu.fits(drop, getOutputSlots())) {
menu.pushItem(drop, getOutputSlots());
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType());
block.setType(Material.AIR);
move(b, face, block);
b.setType(Material.AIR);
BlockStorage.moveBlockInfo(b.getLocation(), block.getLocation());
}
if (event.isCancelled()) {
return;
}
// We only want to break non-Slimefun blocks
SlimefunItem blockId = BlockStorage.check(block);
if (blockId == null) {
for (ItemStack drop : drops) {
if (menu.fits(drop, getOutputSlots())) {
menu.pushItem(drop, getOutputSlots());
}
}
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType());
block.setType(Material.AIR);
move(b, face, block);
}
}
else {
move(b, face, block);
}
}
else {

View File

@ -20,6 +20,7 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Rotatable;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
@ -31,6 +32,7 @@ import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.skull.SkullBlock;
import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
@ -44,12 +46,12 @@ import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu.AdvancedMenu
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
@ -123,48 +125,48 @@ public abstract class ProgrammableAndroid extends SlimefunItem implements Invent
}
};
registerBlockHandler(getID(), new SlimefunBlockHandler() {
registerBlockHandler(getID(), (p, b, stack, reason) -> {
boolean allow = reason == UnregisterReason.PLAYER_BREAK && (BlockStorage.getLocationInfo(b.getLocation(), "owner").equals(p.getUniqueId().toString()) || p.hasPermission("slimefun.android.bypass"));
if (allow) {
BlockMenu inv = BlockStorage.getInventory(b);
if (inv != null) {
inv.dropItems(b.getLocation(), 43);
inv.dropItems(b.getLocation(), getOutputSlots());
}
}
return allow;
});
addItemHandler(onPlace());
}
private ItemHandler onPlace() {
return new BlockPlaceHandler(false) {
@Override
public void onPlace(Player p, Block b, SlimefunItem item) {
public void onPlayerPlace(BlockPlaceEvent e) {
Player p = e.getPlayer();
Block b = e.getBlock();
BlockStorage.addBlockInfo(b, "owner", p.getUniqueId().toString());
BlockStorage.addBlockInfo(b, "script", DEFAULT_SCRIPT);
BlockStorage.addBlockInfo(b, "index", "0");
BlockStorage.addBlockInfo(b, "fuel", "0");
BlockStorage.addBlockInfo(b, "rotation", p.getFacing().getOppositeFace().toString());
BlockStorage.addBlockInfo(b, "paused", "true");
b.setType(Material.PLAYER_HEAD);
Rotatable blockData = (Rotatable) b.getBlockData();
blockData.setRotation(p.getFacing());
BlockData blockData = Material.PLAYER_HEAD.createBlockData(data -> {
if (data instanceof Rotatable) {
((Rotatable) data).setRotation(p.getFacing());
}
});
b.setBlockData(blockData);
}
@Override
public boolean onBreak(Player p, Block b, SlimefunItem item, UnregisterReason reason) {
boolean allow = reason == UnregisterReason.PLAYER_BREAK && (BlockStorage.getLocationInfo(b.getLocation(), "owner").equals(p.getUniqueId().toString()) || p.hasPermission("slimefun.android.bypass"));
if (allow) {
BlockMenu inv = BlockStorage.getInventory(b);
if (inv != null) {
if (inv.getItemInSlot(43) != null) {
b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(43));
inv.replaceExistingItem(43, null);
}
for (int slot : getOutputSlots()) {
if (inv.getItemInSlot(slot) != null) {
b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
inv.replaceExistingItem(slot, null);
}
}
}
}
return allow;
}
});
};
}
/**
@ -172,7 +174,9 @@ public abstract class ProgrammableAndroid extends SlimefunItem implements Invent
*
* @return The type of this {@link ProgrammableAndroid}
*/
public abstract AndroidType getAndroidType();
public AndroidType getAndroidType() {
return AndroidType.NONE;
}
/**
* This returns the {@link AndroidFuelSource} for this {@link ProgrammableAndroid}.
@ -500,7 +504,7 @@ public abstract class ProgrammableAndroid extends SlimefunItem implements Invent
ChestMenu menu = new ChestMenu(ChatColor.DARK_AQUA + SlimefunPlugin.getLocalization().getMessage(p, "android.scripts.editor"));
ChestMenuUtils.drawBackground(menu, 0, 1, 2, 3, 4, 5, 6, 7, 8);
menu.addItem(9, new CustomItem(SlimefunUtils.getCustomHead("16139fd1c5654e56e9e4e2c8be7eb2bd5b499d633616663feee99b74352ad64"), "&rDo nothing"), (pl, slot, item, action) -> {
menu.addItem(9, new CustomItem(SlimefunUtils.getCustomHead("16139fd1c5654e56e9e4e2c8be7eb2bd5b499d633616663feee99b74352ad64"), "&fDo nothing"), (pl, slot, item, action) -> {
String code = deleteInstruction(script, index);
setScript(b.getLocation(), code);
openScript(p, b, code);
@ -683,9 +687,14 @@ public abstract class ProgrammableAndroid extends SlimefunItem implements Invent
BlockFace rotation = POSSIBLE_ROTATIONS.get(index);
Rotatable rotatatable = (Rotatable) b.getBlockData();
rotatatable.setRotation(rotation.getOppositeFace());
b.setBlockData(rotatatable);
BlockData blockData = Material.PLAYER_HEAD.createBlockData(data -> {
if (data instanceof Rotatable) {
Rotatable rotatable = ((Rotatable) data);
rotatable.setRotation(rotation.getOppositeFace());
}
});
b.setBlockData(blockData);
BlockStorage.addBlockInfo(b, "rotation", rotation.name());
}

View File

@ -1,27 +1,33 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.blocks;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Nameable;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.block.Dispenser;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.events.BlockPlacerPlaceEvent;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.core.attributes.NotPlaceable;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockDispenseHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.papermc.lib.PaperLib;
import io.papermc.lib.features.blockstatesnapshot.BlockStateSnapshotResult;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -29,7 +35,18 @@ import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class BlockPlacer extends SimpleSlimefunItem<BlockDispenseHandler> {
/**
* The {@link BlockPlacer} is a machine which can place {@link Block Blocks}, as the name
* would suggest.
* It really just is a special type of {@link Dispenser} which places items instead of
* shooting them.
*
* @author TheBusyBiscuit
*
* @see BlockPlacerPlaceEvent
*
*/
public class BlockPlacer extends SlimefunItem {
private final ItemSetting<List<String>> blacklist = new ItemSetting<>("unplaceable-blocks", MaterialCollections.getAllUnbreakableBlocks().stream().map(Material::name).collect(Collectors.toList()));
@ -37,11 +54,28 @@ public class BlockPlacer extends SimpleSlimefunItem<BlockDispenseHandler> {
super(category, item, recipeType, recipe);
addItemSetting(blacklist);
addItemHandler(onPlace(), onBlockDispense());
}
@Override
public BlockDispenseHandler getItemHandler() {
private BlockPlaceHandler onPlace() {
return new BlockPlaceHandler(false) {
@Override
public void onPlayerPlace(BlockPlaceEvent e) {
Player p = e.getPlayer();
Block b = e.getBlock();
BlockStorage.addBlockInfo(b, "owner", p.getUniqueId().toString());
}
};
}
private BlockDispenseHandler onBlockDispense() {
return (e, dispenser, facedBlock, machine) -> {
if (!hasPermission(dispenser, facedBlock)) {
return;
}
if (isShulkerBox(e.getItem().getType())) {
// Since vanilla Dispensers can already place Shulker boxes, we
// simply fallback to the vanilla behaviour.
@ -50,12 +84,12 @@ public class BlockPlacer extends SimpleSlimefunItem<BlockDispenseHandler> {
e.setCancelled(true);
if ((facedBlock.getType() == null || facedBlock.getType() == Material.AIR) && e.getItem().getType().isBlock() && !isBlacklisted(e.getItem().getType())) {
if (facedBlock.isEmpty() && e.getItem().getType().isBlock() && !isBlacklisted(e.getItem().getType())) {
SlimefunItem item = SlimefunItem.getByItem(e.getItem());
if (item != null) {
// Check if this Item can even be placed down
if (!(item instanceof NotPlaceable) && !SlimefunPlugin.getRegistry().getBlockHandlers().containsKey(item.getID())) {
if (!(item instanceof NotPlaceable)) {
placeSlimefunBlock(item, e.getItem(), facedBlock, dispenser);
}
}
@ -66,6 +100,31 @@ public class BlockPlacer extends SimpleSlimefunItem<BlockDispenseHandler> {
};
}
/**
* This checks whether the {@link Player} who placed down this {@link BlockPlacer} has
* building permissions at that {@link Location}.
*
* @param dispenser
* The {@link Dispenser} who represents our {@link BlockPlacer}
* @param target
* The {@link Block} where it should be placed
*
* @return Whether this action is permitted or not
*/
private boolean hasPermission(Dispenser dispenser, Block target) {
String owner = BlockStorage.getLocationInfo(dispenser.getLocation(), "owner");
if (owner == null) {
// If no owner was set, then we will fallback to the previous behaviour:
// Allowing block placers to bypass protection, newly placed Block placers
// will respect protection plugins.
return true;
}
OfflinePlayer player = Bukkit.getOfflinePlayer(UUID.fromString(owner));
return SlimefunPlugin.getProtectionManager().hasPermission(player, target, ProtectableAction.PLACE_BLOCK);
}
private boolean isShulkerBox(Material type) {
return type == Material.SHULKER_BOX || type.name().endsWith("_SHULKER_BOX");
}
@ -81,54 +140,77 @@ public class BlockPlacer extends SimpleSlimefunItem<BlockDispenseHandler> {
}
private void placeSlimefunBlock(SlimefunItem sfItem, ItemStack item, Block block, Dispenser dispenser) {
block.setType(item.getType());
BlockStorage.store(block, sfItem.getID());
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, item.getType());
BlockPlacerPlaceEvent e = new BlockPlacerPlaceEvent(dispenser.getBlock(), item, block);
Bukkit.getPluginManager().callEvent(e);
if (item.getType() == Material.SPAWNER && sfItem instanceof RepairedSpawner) {
Optional<EntityType> entity = ((RepairedSpawner) sfItem).getEntityType(item);
if (!e.isCancelled()) {
boolean hasItemHandler = sfItem.callItemHandler(BlockPlaceHandler.class, handler -> {
if (handler.isBlockPlacerAllowed()) {
block.setType(item.getType());
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, item.getType());
if (entity.isPresent()) {
CreatureSpawner spawner = (CreatureSpawner) block.getState();
spawner.setSpawnedType(entity.get());
spawner.update(true, false);
BlockStorage.store(block, sfItem.getID());
handler.onBlockPlacerPlace(e);
if (dispenser.getInventory().containsAtLeast(item, 2)) {
dispenser.getInventory().removeItem(new CustomItem(item, 1));
}
else {
Slimefun.runSync(() -> dispenser.getInventory().removeItem(item), 2L);
}
}
});
if (!hasItemHandler) {
block.setType(item.getType());
block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, item.getType());
BlockStorage.store(block, sfItem.getID());
if (dispenser.getInventory().containsAtLeast(item, 2)) {
dispenser.getInventory().removeItem(new CustomItem(item, 1));
}
else {
Slimefun.runSync(() -> dispenser.getInventory().removeItem(item), 2L);
}
}
}
if (dispenser.getInventory().containsAtLeast(item, 2)) {
dispenser.getInventory().removeItem(new CustomItem(item, 1));
}
else {
Slimefun.runSync(() -> dispenser.getInventory().removeItem(item), 2L);
}
}
private void placeBlock(ItemStack item, Block facedBlock, Dispenser dispenser) {
facedBlock.setType(item.getType());
BlockPlacerPlaceEvent e = new BlockPlacerPlaceEvent(dispenser.getBlock(), item, facedBlock);
Bukkit.getPluginManager().callEvent(e);
if (item.hasItemMeta()) {
ItemMeta meta = item.getItemMeta();
if (!e.isCancelled()) {
facedBlock.setType(item.getType());
if (meta.hasDisplayName()) {
BlockState blockState = facedBlock.getState();
if (item.hasItemMeta()) {
ItemMeta meta = item.getItemMeta();
if ((blockState instanceof Nameable)) {
((Nameable) blockState).setCustomName(meta.getDisplayName());
if (meta.hasDisplayName()) {
BlockStateSnapshotResult blockState = PaperLib.getBlockState(facedBlock, false);
if ((blockState.getState() instanceof Nameable)) {
Nameable nameable = ((Nameable) blockState.getState());
nameable.setCustomName(meta.getDisplayName());
if (blockState.isSnapshot()) {
// Update block state after changing name
blockState.getState().update(true, false);
}
}
}
// Update block state after changing name
blockState.update();
}
}
facedBlock.getWorld().playEffect(facedBlock.getLocation(), Effect.STEP_SOUND, item.getType());
facedBlock.getWorld().playEffect(facedBlock.getLocation(), Effect.STEP_SOUND, item.getType());
if (dispenser.getInventory().containsAtLeast(item, 2)) {
dispenser.getInventory().removeItem(new CustomItem(item, 1));
}
else {
Slimefun.runSync(() -> dispenser.getInventory().removeItem(item), 2L);
if (dispenser.getInventory().containsAtLeast(item, 2)) {
dispenser.getInventory().removeItem(new CustomItem(item, 1));
}
else {
Slimefun.runSync(() -> dispenser.getInventory().removeItem(item), 2L);
}
}
}
}

View File

@ -4,10 +4,13 @@ import java.util.concurrent.ThreadLocalRandom;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Furnace;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.papermc.lib.PaperLib;
import io.papermc.lib.features.blockstatesnapshot.BlockStateSnapshotResult;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
@ -40,15 +43,26 @@ public class EnhancedFurnace extends SimpleSlimefunItem<BlockTicker> {
this.fortuneLevel = fortune - 1;
}
public int getSpeed() {
/**
* This returns the processing speed of this {@link EnhancedFurnace}.
*
* @return The processing speed
*/
public int getProcessingSpeed() {
return speed;
}
/**
* This returns the fuel efficiency of this {@link EnhancedFurnace}.
* The fuel efficiency is a multiplier that is applied to any fuel burnt in this {@link EnhancedFurnace}.
*
* @return The fuel multiplier
*/
public int getFuelEfficiency() {
return efficiency;
}
public int getOutput() {
public int getRandomOutputAmount() {
int bonus = ThreadLocalRandom.current().nextInt(fortuneLevel + 2);
return 1 + bonus;
}
@ -64,20 +78,32 @@ public class EnhancedFurnace extends SimpleSlimefunItem<BlockTicker> {
BlockStorage.clearBlockInfo(b);
}
else {
Furnace furnace = (Furnace) b.getState();
BlockStateSnapshotResult result = PaperLib.getBlockState(b, false);
BlockState state = result.getState();
if (furnace.getCookTime() > 0) {
int cookTime = furnace.getCookTime() + getSpeed() * 10;
furnace.setCookTime((short) Math.min(cookTime, furnace.getCookTimeTotal() - 1));
furnace.update(true, false);
// Check if the BlockState is a Furnace and cooking something
if (state instanceof Furnace && ((Furnace) state).getCookTime() > 0) {
setProgress((Furnace) state);
// Only update if necessary
if (result.isSnapshot()) {
state.update(true, false);
}
}
}
}
@Override
public boolean isSynchronized() {
// This messes with BlockStates, so it needs to be synchronized
return true;
}
};
}
private void setProgress(Furnace furnace) {
// Update the cooktime
int cookTime = furnace.getCookTime() + getProcessingSpeed() * 10;
furnace.setCookTime((short) Math.min(cookTime, furnace.getCookTimeTotal() - 1));
}
}

View File

@ -6,51 +6,57 @@ import org.bukkit.block.Block;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.github.thebusybiscuit.slimefun4.utils.holograms.SimpleHologram;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class HologramProjector extends SimpleSlimefunItem<BlockUseHandler> {
public class HologramProjector extends SlimefunItem {
public HologramProjector(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
super(category, item, recipeType, recipe, recipeOutput);
SlimefunItem.registerBlockHandler(getID(), new SlimefunBlockHandler() {
addItemHandler(onPlace(), onRightClick(), onBreak());
}
private BlockPlaceHandler onPlace() {
return new BlockPlaceHandler(false) {
@Override
public void onPlace(Player p, Block b, SlimefunItem item) {
public void onPlayerPlace(BlockPlaceEvent e) {
Block b = e.getBlockPlaced();
BlockStorage.addBlockInfo(b, "text", "Edit me via the Projector");
BlockStorage.addBlockInfo(b, "offset", "0.5");
BlockStorage.addBlockInfo(b, "owner", p.getUniqueId().toString());
BlockStorage.addBlockInfo(b, "owner", e.getPlayer().getUniqueId().toString());
getArmorStand(b, true);
}
@Override
public boolean onBreak(Player p, Block b, SlimefunItem item, UnregisterReason reason) {
remove(b);
return true;
}
});
};
}
@Override
public BlockUseHandler getItemHandler() {
private BlockBreakHandler onBreak() {
return (e, item, fortune, drops) -> {
remove(e.getBlock());
return true;
};
}
public BlockUseHandler onRightClick() {
return e -> {
e.cancel();
@ -77,10 +83,11 @@ public class HologramProjector extends SimpleSlimefunItem<BlockUseHandler> {
BlockStorage.addBlockInfo(projector, "text", hologram.getCustomName());
openEditor(pl, projector);
});
return false;
});
menu.addItem(1, new CustomItem(new ItemStack(Material.CLOCK), "&7Offset: &e" + DoubleHandler.fixDouble(Double.valueOf(BlockStorage.getLocationInfo(projector.getLocation(), "offset")) + 1.0D), "", "&rLeft Click: &7+0.1", "&rRight Click: &7-0.1"));
menu.addItem(1, new CustomItem(Material.CLOCK, "&7Offset: &e" + DoubleHandler.fixDouble(Double.valueOf(BlockStorage.getLocationInfo(projector.getLocation(), "offset")) + 1.0D), "", "&rLeft Click: &7+0.1", "&rRight Click: &7-0.1"));
menu.addMenuClickHandler(1, (pl, slot, item, action) -> {
double offset = DoubleHandler.fixDouble(Double.valueOf(BlockStorage.getLocationInfo(projector.getLocation(), "offset")) + (action.isRightClicked() ? -0.1F : 0.1F));
ArmorStand hologram = getArmorStand(projector, true);

View File

@ -4,18 +4,28 @@ import java.util.Locale;
import java.util.Optional;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.entity.EntityType;
import org.bukkit.event.block.BlockEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.events.BlockPlacerPlaceEvent;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
* A {@link RepairedSpawner} is the repaired variant of a {@link BrokenSpawner}.
*
* @author TheBusyBiscuit
*
* @see BrokenSpawner
*
*/
public class RepairedSpawner extends SimpleSlimefunItem<BlockPlaceHandler> {
public RepairedSpawner(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
@ -24,21 +34,26 @@ public class RepairedSpawner extends SimpleSlimefunItem<BlockPlaceHandler> {
@Override
public BlockPlaceHandler getItemHandler() {
return (p, e, item) -> {
// We need to explicitly ignore the lore here
if (SlimefunUtils.isItemSimilar(item, SlimefunItems.REPAIRED_SPAWNER, false, false)) {
return new BlockPlaceHandler(true) {
@Override
public void onPlayerPlace(BlockPlaceEvent e) {
onPlace(e.getItemInHand(), e);
}
@Override
public void onBlockPlacerPlace(BlockPlacerPlaceEvent e) {
onPlace(e.getItemStack(), e);
}
private void onPlace(ItemStack item, BlockEvent e) {
Optional<EntityType> entity = getEntityType(item);
if (entity.isPresent()) {
if (entity.isPresent() && e.getBlock().getType() == Material.SPAWNER) {
CreatureSpawner spawner = (CreatureSpawner) e.getBlock().getState();
spawner.setSpawnedType(entity.get());
spawner.update(true, false);
}
return true;
}
else {
return false;
}
};
}

View File

@ -2,19 +2,33 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.cargo;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
/**
* This abstract class is the super class of all cargo nodes.
*
* @author TheBusyBiscuit
*
*/
abstract class AbstractCargoNode extends SlimefunItem {
protected static final String FREQUENCY = "frequency";
@ -22,6 +36,21 @@ abstract class AbstractCargoNode extends SlimefunItem {
public AbstractCargoNode(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
super(category, item, recipeType, recipe, recipeOutput);
addItemHandler(new BlockPlaceHandler(false) {
@Override
public void onPlayerPlace(BlockPlaceEvent e) {
Block b = e.getBlock();
// The owner and frequency are required by every node
BlockStorage.addBlockInfo(b, "owner", e.getPlayer().getUniqueId().toString());
BlockStorage.addBlockInfo(b, FREQUENCY, "0");
onPlace(e);
}
});
new BlockMenuPreset(getID(), ChatUtils.removeColorCodes(item.getItemMeta().getDisplayName())) {
@Override
@ -46,6 +75,59 @@ abstract class AbstractCargoNode extends SlimefunItem {
};
}
protected void addChannelSelector(Block b, BlockMenu menu, int slotPrev, int slotCurrent, int slotNext) {
boolean isChestTerminalInstalled = SlimefunPlugin.getThirdPartySupportService().isChestTerminalInstalled();
menu.replaceExistingItem(slotPrev, new CustomItem(SlimefunUtils.getCustomHead(HeadTexture.CARGO_ARROW_LEFT.getTexture()), "&bPrevious Channel", "", "&e> Click to decrease the Channel ID by 1"));
menu.addMenuClickHandler(slotPrev, (p, slot, item, action) -> {
int channel = Integer.parseInt(BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY)) - 1;
if (channel < 0) {
if (isChestTerminalInstalled) {
channel = 16;
}
else {
channel = 15;
}
}
BlockStorage.addBlockInfo(b, FREQUENCY, String.valueOf(channel));
updateBlockMenu(menu, b);
return false;
});
int channel = ((!BlockStorage.hasBlockInfo(b) || BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY) == null) ? 0 : (Integer.parseInt(BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY))));
if (channel == 16) {
menu.replaceExistingItem(slotCurrent, new CustomItem(SlimefunUtils.getCustomHead(HeadTexture.CHEST_TERMINAL.getTexture()), "&bChannel ID: &3" + (channel + 1)));
menu.addMenuClickHandler(slotCurrent, ChestMenuUtils.getEmptyClickHandler());
}
else {
menu.replaceExistingItem(slotCurrent, new CustomItem(MaterialCollections.getAllWoolColors().get(channel), "&bChannel ID: &3" + (channel + 1)));
menu.addMenuClickHandler(slotCurrent, ChestMenuUtils.getEmptyClickHandler());
}
menu.replaceExistingItem(slotNext, new CustomItem(SlimefunUtils.getCustomHead(HeadTexture.CARGO_ARROW_RIGHT.getTexture()), "&bNext Channel", "", "&e> Click to increase the Channel ID by 1"));
menu.addMenuClickHandler(slotNext, (p, slot, item, action) -> {
int channeln = Integer.parseInt(BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY)) + 1;
if (isChestTerminalInstalled) {
if (channeln > 16) {
channeln = 0;
}
}
else if (channeln > 15) {
channeln = 0;
}
BlockStorage.addBlockInfo(b, FREQUENCY, String.valueOf(channeln));
updateBlockMenu(menu, b);
return false;
});
}
protected abstract void onPlace(BlockPlaceEvent e);
protected abstract void createBorder(BlockMenuPreset preset);
protected abstract void updateBlockMenu(BlockMenu menu, Block b);

View File

@ -0,0 +1,140 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.cargo;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
/**
* This abstract super class represents all filtered Cargo nodes.
*
* @author TheBusyBiscuit
*
* @see CargoInputNode
* @see AdvancedCargoOutputNode
*
*/
abstract class AbstractFilterNode extends AbstractCargoNode {
protected static final int[] SLOTS = { 19, 20, 21, 28, 29, 30, 37, 38, 39 };
public AbstractFilterNode(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
super(category, item, recipeType, recipe, recipeOutput);
registerBlockHandler(getID(), (p, b, stack, reason) -> {
BlockMenu inv = BlockStorage.getInventory(b);
if (inv != null) {
inv.dropItems(b.getLocation(), SLOTS);
}
return true;
});
}
protected abstract int[] getBorder();
@Override
protected void onPlace(BlockPlaceEvent e) {
Block b = e.getBlock();
BlockStorage.addBlockInfo(b, "index", "0");
BlockStorage.addBlockInfo(b, "filter-type", "whitelist");
BlockStorage.addBlockInfo(b, "filter-lore", String.valueOf(true));
BlockStorage.addBlockInfo(b, "filter-durability", String.valueOf(false));
}
@Override
protected void createBorder(BlockMenuPreset preset) {
for (int i : getBorder()) {
preset.addItem(i, new CustomItem(Material.CYAN_STAINED_GLASS_PANE, " "), ChestMenuUtils.getEmptyClickHandler());
}
preset.addItem(2, new CustomItem(Material.PAPER, "&3Items", "", "&bPut in all Items you want to", "&bblacklist/whitelist"), ChestMenuUtils.getEmptyClickHandler());
}
@Override
protected void updateBlockMenu(BlockMenu menu, Block b) {
String filterType = BlockStorage.getLocationInfo(b.getLocation(), "filter-type");
if (!BlockStorage.hasBlockInfo(b) || filterType == null || filterType.equals("whitelist")) {
menu.replaceExistingItem(15, new CustomItem(Material.WHITE_WOOL, "&7Type: &rWhitelist", "", "&e> Click to change it to Blacklist"));
menu.addMenuClickHandler(15, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-type", "blacklist");
updateBlockMenu(menu, b);
return false;
});
}
else {
menu.replaceExistingItem(15, new CustomItem(Material.BLACK_WOOL, "&7Type: &8Blacklist", "", "&e> Click to change it to Whitelist"));
menu.addMenuClickHandler(15, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-type", "whitelist");
updateBlockMenu(menu, b);
return false;
});
}
String durability = BlockStorage.getLocationInfo(b.getLocation(), "filter-durability");
if (!BlockStorage.hasBlockInfo(b) || durability == null || durability.equals(String.valueOf(false))) {
ItemStack is = new ItemStack(Material.STONE_SWORD);
ItemMeta meta = is.getItemMeta();
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
is.setItemMeta(meta);
menu.replaceExistingItem(16, new CustomItem(is, "&7Include Sub-IDs/Durability: &4\u2718", "", "&e> Click to toggle whether the Durability has to match"));
menu.addMenuClickHandler(16, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-durability", String.valueOf(true));
updateBlockMenu(menu, b);
return false;
});
}
else {
ItemStack is = new ItemStack(Material.GOLDEN_SWORD);
ItemMeta meta = is.getItemMeta();
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
((Damageable) meta).setDamage(20);
is.setItemMeta(meta);
menu.replaceExistingItem(16, new CustomItem(is, "&7Include Sub-IDs/Durability: &2\u2714", "", "&e> Click to toggle whether the Durability has to match"));
menu.addMenuClickHandler(16, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-durability", String.valueOf(false));
updateBlockMenu(menu, b);
return false;
});
}
String lore = BlockStorage.getLocationInfo(b.getLocation(), "filter-lore");
if (!BlockStorage.hasBlockInfo(b) || lore == null || lore.equals(String.valueOf(true))) {
menu.replaceExistingItem(25, new CustomItem(Material.MAP, "&7Include Lore: &2\u2714", "", "&e> Click to toggle whether the Lore has to match"));
menu.addMenuClickHandler(25, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-lore", String.valueOf(false));
updateBlockMenu(menu, b);
return false;
});
}
else {
menu.replaceExistingItem(25, new CustomItem(Material.MAP, "&7Include Lore: &4\u2718", "", "&e> Click to toggle whether the Lore has to match"));
menu.addMenuClickHandler(25, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-lore", String.valueOf(true));
updateBlockMenu(menu, b);
return false;
});
}
addChannelSelector(b, menu, 41, 42, 43);
}
}

View File

@ -1,169 +1,22 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.cargo;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
public class AdvancedCargoOutputNode extends AbstractCargoNode {
public class AdvancedCargoOutputNode extends AbstractFilterNode {
private static final int[] BORDER = { 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 22, 23, 24, 26, 27, 31, 32, 33, 34, 35, 36, 40, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 };
private static final int[] SLOTS = { 19, 20, 21, 28, 29, 30, 37, 38, 39 };
public AdvancedCargoOutputNode(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
super(category, item, recipeType, recipe, recipeOutput);
registerBlockHandler(getID(), new SlimefunBlockHandler() {
@Override
public void onPlace(Player p, Block b, SlimefunItem item) {
BlockStorage.addBlockInfo(b, "owner", p.getUniqueId().toString());
BlockStorage.addBlockInfo(b, "index", "0");
BlockStorage.addBlockInfo(b, FREQUENCY, "0");
BlockStorage.addBlockInfo(b, "filter-type", "whitelist");
BlockStorage.addBlockInfo(b, "filter-lore", String.valueOf(true));
BlockStorage.addBlockInfo(b, "filter-durability", String.valueOf(false));
}
@Override
public boolean onBreak(Player p, Block b, SlimefunItem item, UnregisterReason reason) {
BlockMenu inv = BlockStorage.getInventory(b);
if (inv != null) {
for (int slot : SLOTS) {
if (inv.getItemInSlot(slot) != null) {
b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
inv.replaceExistingItem(slot, null);
}
}
}
return true;
}
});
public AdvancedCargoOutputNode(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe, null);
}
@Override
protected void createBorder(BlockMenuPreset preset) {
for (int i : BORDER) {
preset.addItem(i, new CustomItem(Material.CYAN_STAINED_GLASS_PANE, " "), ChestMenuUtils.getEmptyClickHandler());
}
preset.addItem(2, new CustomItem(Material.PAPER, "&3Items", "", "&bPut in all Items you want to", "&bblacklist/whitelist"), ChestMenuUtils.getEmptyClickHandler());
}
@Override
protected void updateBlockMenu(BlockMenu menu, Block b) {
if (!BlockStorage.hasBlockInfo(b) || BlockStorage.getLocationInfo(b.getLocation(), "filter-type") == null || BlockStorage.getLocationInfo(b.getLocation(), "filter-type").equals("whitelist")) {
menu.replaceExistingItem(15, new CustomItem(Material.WHITE_WOOL, "&7Type: &rWhitelist", "", "&e> Click to change it to Blacklist"));
menu.addMenuClickHandler(15, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-type", "blacklist");
updateBlockMenu(menu, b);
return false;
});
}
else {
menu.replaceExistingItem(15, new CustomItem(Material.BLACK_WOOL, "&7Type: &8Blacklist", "", "&e> Click to change it to Whitelist"));
menu.addMenuClickHandler(15, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-type", "whitelist");
updateBlockMenu(menu, b);
return false;
});
}
if (!BlockStorage.hasBlockInfo(b) || BlockStorage.getLocationInfo(b.getLocation(), "filter-durability") == null || BlockStorage.getLocationInfo(b.getLocation(), "filter-durability").equals(String.valueOf(false))) {
menu.replaceExistingItem(16, new CustomItem(Material.STONE_SWORD, "&7Include Sub-IDs/Durability: &4\u2718", "", "&e> Click to toggle whether the Durability has to match"));
menu.addMenuClickHandler(16, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-durability", String.valueOf(true));
updateBlockMenu(menu, b);
return false;
});
}
else {
ItemStack is = new ItemStack(Material.GOLDEN_SWORD);
Damageable dmg = (Damageable) is.getItemMeta();
dmg.setDamage(20);
is.setItemMeta((ItemMeta) dmg);
menu.replaceExistingItem(16, new CustomItem(is, "&7Include Sub-IDs/Durability: &2\u2714", "", "&e> Click to toggle whether the Durability has to match"));
menu.addMenuClickHandler(16, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-durability", String.valueOf(false));
updateBlockMenu(menu, b);
return false;
});
}
if (!BlockStorage.hasBlockInfo(b) || BlockStorage.getLocationInfo(b.getLocation(), "filter-lore") == null || BlockStorage.getLocationInfo(b.getLocation(), "filter-lore").equals(String.valueOf(true))) {
menu.replaceExistingItem(25, new CustomItem(Material.MAP, "&7Include Lore: &2\u2714", "", "&e> Click to toggle whether the Lore has to match"));
menu.addMenuClickHandler(25, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-lore", String.valueOf(false));
updateBlockMenu(menu, b);
return false;
});
}
else {
menu.replaceExistingItem(25, new CustomItem(Material.MAP, "&7Include Lore: &4\u2718", "", "&e> Click to toggle whether the Lore has to match"));
menu.addMenuClickHandler(25, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-lore", String.valueOf(true));
updateBlockMenu(menu, b);
return false;
});
}
menu.replaceExistingItem(41, new CustomItem(SlimefunUtils.getCustomHead("f2599bd986659b8ce2c4988525c94e19ddd39fad08a38284a197f1b70675acc"), "&bChannel", "", "&e> Click to decrease the Channel ID by 1"));
menu.addMenuClickHandler(41, (p, slot, item, action) -> {
int channel = Integer.parseInt(BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY)) - 1;
if (channel < 0) {
if (SlimefunPlugin.getThirdPartySupportService().isChestTerminalInstalled()) channel = 16;
else channel = 15;
}
BlockStorage.addBlockInfo(b, FREQUENCY, String.valueOf(channel));
updateBlockMenu(menu, b);
return false;
});
int channel = ((!BlockStorage.hasBlockInfo(b) || BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY) == null) ? 0 : (Integer.parseInt(BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY))));
if (channel == 16) {
menu.replaceExistingItem(42, new CustomItem(SlimefunUtils.getCustomHead("7a44ff3a5f49c69cab676bad8d98a063fa78cfa61916fdef3e267557fec18283"), "&bChannel ID: &3" + (channel + 1)));
menu.addMenuClickHandler(42, ChestMenuUtils.getEmptyClickHandler());
}
else {
menu.replaceExistingItem(42, new CustomItem(MaterialCollections.getAllWoolColors().get(channel), "&bChannel ID: &3" + (channel + 1)));
menu.addMenuClickHandler(42, ChestMenuUtils.getEmptyClickHandler());
}
menu.replaceExistingItem(43, new CustomItem(SlimefunUtils.getCustomHead("c2f910c47da042e4aa28af6cc81cf48ac6caf37dab35f88db993accb9dfe516"), "&bChannel", "", "&e> Click to increase the Channel ID by 1"));
menu.addMenuClickHandler(43, (p, slot, item, action) -> {
int channeln = Integer.parseInt(BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY)) + 1;
if (SlimefunPlugin.getThirdPartySupportService().isChestTerminalInstalled()) {
if (channeln > 16) channeln = 0;
}
else {
if (channeln > 15) channeln = 0;
}
BlockStorage.addBlockInfo(b, FREQUENCY, String.valueOf(channeln));
updateBlockMenu(menu, b);
return false;
});
protected int[] getBorder() {
return BORDER;
}
}

View File

@ -1,117 +1,44 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.cargo;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
public class CargoInputNode extends AbstractCargoNode {
public class CargoInputNode extends AbstractFilterNode {
private static final int[] BORDER = { 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 22, 23, 26, 27, 31, 32, 33, 34, 35, 36, 40, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 };
private static final int[] SLOTS = { 19, 20, 21, 28, 29, 30, 37, 38, 39 };
public CargoInputNode(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
super(category, item, recipeType, recipe, recipeOutput);
registerBlockHandler(getID(), new SlimefunBlockHandler() {
@Override
public void onPlace(Player p, Block b, SlimefunItem item) {
BlockStorage.addBlockInfo(b, "owner", p.getUniqueId().toString());
BlockStorage.addBlockInfo(b, "index", "0");
BlockStorage.addBlockInfo(b, FREQUENCY, "0");
BlockStorage.addBlockInfo(b, "filter-type", "whitelist");
BlockStorage.addBlockInfo(b, "filter-lore", String.valueOf(true));
BlockStorage.addBlockInfo(b, "filter-durability", String.valueOf(false));
BlockStorage.addBlockInfo(b, "round-robin", String.valueOf(false));
}
@Override
public boolean onBreak(Player p, Block b, SlimefunItem item, UnregisterReason reason) {
BlockMenu inv = BlockStorage.getInventory(b);
if (inv != null) {
for (int slot : SLOTS) {
if (inv.getItemInSlot(slot) != null) {
b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
inv.replaceExistingItem(slot, null);
}
}
}
return true;
}
});
}
@Override
protected void createBorder(BlockMenuPreset preset) {
for (int i : BORDER) {
preset.addItem(i, new CustomItem(Material.CYAN_STAINED_GLASS_PANE, " "), ChestMenuUtils.getEmptyClickHandler());
}
protected int[] getBorder() {
return BORDER;
}
preset.addItem(2, new CustomItem(Material.PAPER, "&3Items", "", "&bPut in all Items you want to", "&bblacklist/whitelist"), ChestMenuUtils.getEmptyClickHandler());
@Override
protected void onPlace(BlockPlaceEvent e) {
super.onPlace(e);
BlockStorage.addBlockInfo(e.getBlock(), "round-robin", String.valueOf(false));
}
@Override
protected void updateBlockMenu(BlockMenu menu, Block b) {
if (!BlockStorage.hasBlockInfo(b) || BlockStorage.getLocationInfo(b.getLocation(), "filter-type") == null || BlockStorage.getLocationInfo(b.getLocation(), "filter-type").equals("whitelist")) {
menu.replaceExistingItem(15, new CustomItem(Material.WHITE_WOOL, "&7Type: &rWhitelist", "", "&e> Click to change it to Blacklist"));
menu.addMenuClickHandler(15, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-type", "blacklist");
updateBlockMenu(menu, b);
return false;
});
}
else {
menu.replaceExistingItem(15, new CustomItem(Material.BLACK_WOOL, "&7Type: &8Blacklist", "", "&e> Click to change it to Whitelist"));
menu.addMenuClickHandler(15, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-type", "whitelist");
updateBlockMenu(menu, b);
return false;
});
}
super.updateBlockMenu(menu, b);
if (!BlockStorage.hasBlockInfo(b) || BlockStorage.getLocationInfo(b.getLocation(), "filter-durability") == null || BlockStorage.getLocationInfo(b.getLocation(), "filter-durability").equals(String.valueOf(false))) {
menu.replaceExistingItem(16, new CustomItem(Material.STONE_SWORD, "&7Include Sub-IDs/Durability: &4\u2718", "", "&e> Click to toggle whether the Durability has to match"));
menu.addMenuClickHandler(16, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-durability", String.valueOf(true));
updateBlockMenu(menu, b);
return false;
});
}
else {
ItemStack is = new ItemStack(Material.GOLDEN_SWORD);
Damageable dmg = (Damageable) is.getItemMeta();
dmg.setDamage(20);
is.setItemMeta((ItemMeta) dmg);
menu.replaceExistingItem(16, new CustomItem(is, "&7Include Sub-IDs/Durability: &2\u2714", "", "&e> Click to toggle whether the Durability has to match"));
menu.addMenuClickHandler(16, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-durability", String.valueOf(false));
updateBlockMenu(menu, b);
return false;
});
}
if (!BlockStorage.hasBlockInfo(b) || BlockStorage.getLocationInfo(b.getLocation(), "round-robin") == null || BlockStorage.getLocationInfo(b.getLocation(), "round-robin").equals(String.valueOf(false))) {
menu.replaceExistingItem(24, new CustomItem(SlimefunUtils.getCustomHead("d78f2b7e5e75639ea7fb796c35d364c4df28b4243e66b76277aadcd6261337"), "&7Round-Robin Mode: &4\u2718", "", "&e> Click to enable Round Robin Mode", "&e(Items will be equally distributed on the Channel)"));
String roundRobinMode = BlockStorage.getLocationInfo(b.getLocation(), "round-robin");
if (!BlockStorage.hasBlockInfo(b) || roundRobinMode == null || roundRobinMode.equals(String.valueOf(false))) {
menu.replaceExistingItem(24, new CustomItem(SlimefunUtils.getCustomHead(HeadTexture.ENERGY_REGULATOR.getTexture()), "&7Round-Robin Mode: &4\u2718", "", "&e> Click to enable Round Robin Mode", "&e(Items will be equally distributed on the Channel)"));
menu.addMenuClickHandler(24, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "round-robin", String.valueOf(true));
updateBlockMenu(menu, b);
@ -119,69 +46,13 @@ public class CargoInputNode extends AbstractCargoNode {
});
}
else {
menu.replaceExistingItem(24, new CustomItem(SlimefunUtils.getCustomHead("d78f2b7e5e75639ea7fb796c35d364c4df28b4243e66b76277aadcd6261337"), "&7Round-Robin Mode: &2\u2714", "", "&e> Click to disable Round Robin Mode", "&e(Items will be equally distributed on the Channel)"));
menu.replaceExistingItem(24, new CustomItem(SlimefunUtils.getCustomHead(HeadTexture.ENERGY_REGULATOR.getTexture()), "&7Round-Robin Mode: &2\u2714", "", "&e> Click to disable Round Robin Mode", "&e(Items will be equally distributed on the Channel)"));
menu.addMenuClickHandler(24, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "round-robin", String.valueOf(false));
updateBlockMenu(menu, b);
return false;
});
}
if (!BlockStorage.hasBlockInfo(b) || BlockStorage.getLocationInfo(b.getLocation(), "filter-lore") == null || BlockStorage.getLocationInfo(b.getLocation(), "filter-lore").equals(String.valueOf(true))) {
menu.replaceExistingItem(25, new CustomItem(Material.MAP, "&7Include Lore: &2\u2714", "", "&e> Click to toggle whether the Lore has to match"));
menu.addMenuClickHandler(25, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-lore", String.valueOf(false));
updateBlockMenu(menu, b);
return false;
});
}
else {
menu.replaceExistingItem(25, new CustomItem(Material.MAP, "&7Include Lore: &4\u2718", "", "&e> Click to toggle whether the Lore has to match"));
menu.addMenuClickHandler(25, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "filter-lore", String.valueOf(true));
updateBlockMenu(menu, b);
return false;
});
}
menu.replaceExistingItem(41, new CustomItem(SlimefunUtils.getCustomHead("f2599bd986659b8ce2c4988525c94e19ddd39fad08a38284a197f1b70675acc"), "&bChannel", "", "&e> Click to decrease the Channel ID by 1"));
menu.addMenuClickHandler(41, (p, slot, item, action) -> {
int channel = Integer.parseInt(BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY)) - 1;
if (channel < 0) {
if (SlimefunPlugin.getThirdPartySupportService().isChestTerminalInstalled()) channel = 16;
else channel = 15;
}
BlockStorage.addBlockInfo(b, FREQUENCY, String.valueOf(channel));
updateBlockMenu(menu, b);
return false;
});
int channel = ((!BlockStorage.hasBlockInfo(b) || BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY) == null) ? 0 : (Integer.parseInt(BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY))));
if (channel == 16) {
menu.replaceExistingItem(42, new CustomItem(SlimefunUtils.getCustomHead("7a44ff3a5f49c69cab676bad8d98a063fa78cfa61916fdef3e267557fec18283"), "&bChannel ID: &3" + (channel + 1)));
menu.addMenuClickHandler(42, ChestMenuUtils.getEmptyClickHandler());
}
else {
menu.replaceExistingItem(42, new CustomItem(new ItemStack(MaterialCollections.getAllWoolColors().get(channel)), "&bChannel ID: &3" + (channel + 1)));
menu.addMenuClickHandler(42, ChestMenuUtils.getEmptyClickHandler());
}
menu.replaceExistingItem(43, new CustomItem(SlimefunUtils.getCustomHead("c2f910c47da042e4aa28af6cc81cf48ac6caf37dab35f88db993accb9dfe516"), "&bChannel", "", "&e> Click to increase the Channel ID by 1"));
menu.addMenuClickHandler(43, (p, slot, item, action) -> {
int channeln = Integer.parseInt(BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY)) + 1;
if (SlimefunPlugin.getThirdPartySupportService().isChestTerminalInstalled()) {
if (channeln > 16) channeln = 0;
}
else {
if (channeln > 15) channeln = 0;
}
BlockStorage.addBlockInfo(b, FREQUENCY, String.valueOf(channeln));
updateBlockMenu(menu, b);
return false;
});
}
}

View File

@ -2,20 +2,13 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.cargo;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
@ -26,20 +19,11 @@ public class CargoOutputNode extends AbstractCargoNode {
public CargoOutputNode(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
super(category, item, recipeType, recipe, recipeOutput);
}
registerBlockHandler(getID(), new SlimefunBlockHandler() {
@Override
public void onPlace(Player p, Block b, SlimefunItem item) {
BlockStorage.addBlockInfo(b, "owner", p.getUniqueId().toString());
BlockStorage.addBlockInfo(b, FREQUENCY, "0");
}
@Override
public boolean onBreak(Player p, Block b, SlimefunItem item, UnregisterReason reason) {
return true;
}
});
@Override
protected void onPlace(BlockPlaceEvent e) {
// We only require the default values
}
@Override
@ -51,46 +35,7 @@ public class CargoOutputNode extends AbstractCargoNode {
@Override
protected void updateBlockMenu(BlockMenu menu, Block b) {
menu.replaceExistingItem(12, new CustomItem(SlimefunUtils.getCustomHead("f2599bd986659b8ce2c4988525c94e19ddd39fad08a38284a197f1b70675acc"), "&bChannel", "", "&e> Click to decrease the Channel ID by 1"));
menu.addMenuClickHandler(12, (p, slot, item, action) -> {
int channel = Integer.parseInt(BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY)) - 1;
if (channel < 0) {
if (SlimefunPlugin.getThirdPartySupportService().isChestTerminalInstalled()) channel = 16;
else channel = 15;
}
BlockStorage.addBlockInfo(b, FREQUENCY, String.valueOf(channel));
updateBlockMenu(menu, b);
return false;
});
int channel = ((!BlockStorage.hasBlockInfo(b) || BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY) == null) ? 0 : (Integer.parseInt(BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY))));
if (channel == 16) {
menu.replaceExistingItem(13, new CustomItem(SlimefunUtils.getCustomHead("7a44ff3a5f49c69cab676bad8d98a063fa78cfa61916fdef3e267557fec18283"), "&bChannel ID: &3" + (channel + 1)));
menu.addMenuClickHandler(13, ChestMenuUtils.getEmptyClickHandler());
}
else {
menu.replaceExistingItem(13, new CustomItem(MaterialCollections.getAllWoolColors().get(channel), "&bChannel ID: &3" + (channel + 1)));
menu.addMenuClickHandler(13, ChestMenuUtils.getEmptyClickHandler());
}
menu.replaceExistingItem(14, new CustomItem(SlimefunUtils.getCustomHead("c2f910c47da042e4aa28af6cc81cf48ac6caf37dab35f88db993accb9dfe516"), "&bChannel", "", "&e> Click to increase the Channel ID by 1"));
menu.addMenuClickHandler(14, (p, slot, item, action) -> {
int channeln = Integer.parseInt(BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY)) + 1;
if (SlimefunPlugin.getThirdPartySupportService().isChestTerminalInstalled()) {
if (channeln > 16) channeln = 0;
}
else {
if (channeln > 15) channeln = 0;
}
BlockStorage.addBlockInfo(b, FREQUENCY, String.valueOf(channeln));
updateBlockMenu(menu, b);
return false;
});
addChannelSelector(b, menu, 12, 13, 14);
}
}

View File

@ -102,27 +102,11 @@ public class ReactorAccessPort extends SlimefunItem {
BlockMenu inv = BlockStorage.getInventory(b);
if (inv != null) {
for (int slot : getFuelSlots()) {
if (inv.getItemInSlot(slot) != null) {
b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
inv.replaceExistingItem(slot, null);
}
}
for (int slot : getCoolantSlots()) {
if (inv.getItemInSlot(slot) != null) {
b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
inv.replaceExistingItem(slot, null);
}
}
for (int slot : getOutputSlots()) {
if (inv.getItemInSlot(slot) != null) {
b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
inv.replaceExistingItem(slot, null);
}
}
inv.dropItems(b.getLocation(), getFuelSlots());
inv.dropItems(b.getLocation(), getCoolantSlots());
inv.dropItems(b.getLocation(), getOutputSlots());
}
return true;
});
}

View File

@ -5,7 +5,6 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.bukkit.Location;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
@ -17,14 +16,12 @@ import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.reactors.Reactor;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock;
import me.mrCookieSlime.Slimefun.Objects.handlers.GeneratorTicker;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
@ -32,6 +29,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
*
* @author TheBusyBiscuit
*
* @see EnergyNetProvider
* @see AGenerator
* @see Reactor
*
@ -81,56 +79,12 @@ public abstract class AbstractEnergyProvider extends SlimefunItem implements Inv
return EnergyNetComponentType.GENERATOR;
}
/**
* @deprecated Please implement the methods
* {@link #getGeneratedOutput(org.bukkit.Location, me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config)}
* and {@link #willExplode(org.bukkit.Location, me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config)}
* instead
*
* @return A {@link GeneratorTicker}
*/
@Deprecated
protected GeneratorTicker onTick() {
return null;
}
@Override
public int getGeneratedOutput(Location l, Config data) {
if (generatorTicker != null) {
return (int) generatorTicker.generateEnergy(l, this, data);
}
else {
return 0;
}
}
@Override
public boolean willExplode(Location l, Config data) {
if (generatorTicker != null) {
return generatorTicker.explode(l);
}
else {
return false;
}
}
@Override
public void preRegister() {
super.preRegister();
GeneratorTicker ticker = onTick();
if (ticker != null) {
addItemHandler(ticker);
}
}
public void registerFuel(MachineFuel fuel) {
fuelTypes.add(fuel);
}
public Set<MachineFuel> getFuelTypes() {
return this.fuelTypes;
return fuelTypes;
}
@Override

View File

@ -1,18 +1,17 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.electric;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNet;
import io.github.thebusybiscuit.slimefun4.utils.holograms.SimpleHologram;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunBlockHandler;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
@ -31,24 +30,26 @@ public class EnergyRegulator extends SlimefunItem {
public EnergyRegulator(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
SlimefunItem.registerBlockHandler(getID(), new SlimefunBlockHandler() {
@Override
public void onPlace(Player p, Block b, SlimefunItem item) {
// Spawn the hologram
SimpleHologram.update(b, "&7Connecting...");
}
@Override
public boolean onBreak(Player p, Block b, SlimefunItem item, UnregisterReason reason) {
SimpleHologram.remove(b);
return true;
}
SlimefunItem.registerBlockHandler(getID(), (p, b, stack, reason) -> {
SimpleHologram.remove(b);
return true;
});
}
private BlockPlaceHandler onPlace() {
return new BlockPlaceHandler(false) {
@Override
public void onPlayerPlace(BlockPlaceEvent e) {
SimpleHologram.update(e.getBlock(), "&7Connecting...");
}
};
}
@Override
public void preRegister() {
addItemHandler(onPlace());
addItemHandler(new BlockTicker() {
@Override
@ -58,9 +59,13 @@ public class EnergyRegulator extends SlimefunItem {
@Override
public void tick(Block b, SlimefunItem item, Config data) {
EnergyNet.getNetworkFromLocationOrCreate(b.getLocation()).tick(b);
EnergyRegulator.this.tick(b);
}
});
}
private void tick(Block b) {
EnergyNet.getNetworkFromLocationOrCreate(b.getLocation()).tick(b);
}
}

View File

@ -11,8 +11,9 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.core.attributes.Rechargeable;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.EntityInteractHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.core.handlers.ToolUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
@ -42,6 +43,21 @@ public class MultiTool extends SlimefunItem implements Rechargeable {
return capacity;
}
private int nextIndex(int i) {
int index = i;
do {
index++;
if (index >= modes.size()) {
index = 0;
}
}
while (index != i && !modes.get(index).isEnabled());
return index;
}
protected ItemUseHandler getItemUseHandler() {
return e -> {
Player p = e.getPlayer();
@ -64,35 +80,32 @@ public class MultiTool extends SlimefunItem implements Rechargeable {
SlimefunItem selectedItem = modes.get(index).getItem();
String itemName = selectedItem != null ? selectedItem.getItemName() : "Unknown";
SlimefunPlugin.getLocalization().sendMessage(p, "messages.mode-change", true, msg -> msg.replace("%device%", "Multi Tool").replace("%mode%", ChatColor.stripColor(itemName)));
SlimefunPlugin.getLocalization().sendMessage(p, "messages.multi-tool.mode-change", true, msg -> msg.replace("%device%", "Multi Tool").replace("%mode%", ChatColor.stripColor(itemName)));
selectedMode.put(p.getUniqueId(), index);
}
};
}
private int nextIndex(int i) {
int index = i;
do {
index++;
if (index >= modes.size()) {
index = 0;
}
}
while (index != i && !modes.get(index).isEnabled());
return index;
private ToolUseHandler getToolUseHandler() {
return (e, tool, fortune, drops) -> {
SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.multi-tool.not-shears");
e.setCancelled(true);
};
}
private BlockBreakHandler getBlockBreakHandler() {
return (e, item, fortune, drops) -> {
if (isItem(item)) {
private EntityInteractHandler getEntityInteractionHandler() {
return (e, item, offhand) -> {
// Fixes #2217 - Prevent them from being used to shear entities
switch (e.getRightClicked().getType()) {
case MUSHROOM_COW:
case SHEEP:
case SNOWMAN:
SlimefunPlugin.getLocalization().sendMessage(e.getPlayer(), "messages.multi-tool.not-shears");
e.setCancelled(true);
return true;
break;
default:
break;
}
return false;
};
}
@ -101,7 +114,8 @@ public class MultiTool extends SlimefunItem implements Rechargeable {
super.preRegister();
addItemHandler(getItemUseHandler());
addItemHandler(getBlockBreakHandler());
addItemHandler(getToolUseHandler());
addItemHandler(getEntityInteractionHandler());
}
}

View File

@ -11,23 +11,23 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public abstract class LavaGenerator extends AGenerator {
public LavaGenerator(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
}
public LavaGenerator(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
}
@Override
protected void registerDefaultFuelTypes() {
registerFuel(new MachineFuel(40, new ItemStack(Material.LAVA_BUCKET)));
}
registerFuel(new MachineFuel(40, new ItemStack(Material.LAVA_BUCKET)));
}
@Override
public ItemStack getProgressBar() {
return new ItemStack(Material.FLINT_AND_STEEL);
}
@Override
public ItemStack getProgressBar() {
return new ItemStack(Material.FLINT_AND_STEEL);
}
@Override
public String getInventoryTitle() {
return "&4Lava Generator";
}
@Override
public String getInventoryTitle() {
return "&4Lava Generator";
}
}

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