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

Merge branch 'master' into experimental

This commit is contained in:
TheBusyBiscuit 2020-09-02 10:34:13 +02:00 committed by GitHub
commit 7da5b9ad35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
65 changed files with 1296 additions and 1384 deletions

74
.github/CODE_OF_CONDUCT.md vendored Normal file
View File

@ -0,0 +1,74 @@
# Slimefun4 - Code of Conduct
### What is a Code of Conduct?
> A code of conduct is a document that establishes expectations for behavior for your projects participants.
> Adopting, and enforcing, a code of conduct can help create a positive social atmosphere for your community.
<br>\- *Source: [https://opensource.guide](https://opensource.guide/code-of-conduct/#why-do-i-need-a-code-of-conduct)*
This document should serve the purpose of outlining the behaviour we expect from any participant of the project.
## Scope
This Code of Conduct applies to all sections of the [Slimefun4 GitHub repository](https://github.com/TheBusyBiscuit/Slimefun4), our [Slimefun GitHub organization](https://github.com/Slimefun) and all repositories owned by said organization.<br>
For our official Discord server, please refer to our article on [Discord Rules](https://github.com/TheBusyBiscuit/Slimefun4/wiki/Discord-Rules).
Everyone who engages with this project on any of these repositories is expected to follow the Code of Conduct.<br>
This includes maintainers, contributors, sponsors and anyone who engages in the "Issues" section on GitHub.
## Engagement
This is an Open-Source project, anyone is welcome to engage and contribute!<br>
We generally expect users to engage in the Issues section by reporting bugs or commenting on bug reports to give additional context, help, guidance or to propose possible solutions and fixes.
Pull Requests are very much welcome and encouraged! They keep the project alive, so if you see an Issue and know how to fix it, feel free to create a Pull Request!
Issues that are considered "good first issues", indicated by the [good first issue](https://github.com/TheBusyBiscuit/Slimefun4/labels/good%20first%20issue) label, are generally expected to be beginner-friendly.
And even if you shouldn't know where to start or how to proceed, our [Discord Server](https://github.com/TheBusyBiscuit/Slimefun4#discord) and its community will be there for you!
When commenting, please keep in mind that this software is offered for **free**. Don't expect to receive lightning-fast replies 24 hours a day.
Everyone here works on this project in their free time and usually has work, school, university or family to take care of, so we appreciate patience and understanding.
## Our Standards
Examples of behavior that contributes to a positive environment for our community include but are not limited to:
* Demonstrating empathy and kindness towards other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall community
* Having patience and understanding for contributors, even if reply times are slow
<hr>
Examples of unacceptable behavior include but are not limited to:
* The use of sexualized language or imagery, and sexual attention or advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address, without their explicit permission
* Impatient, aggresive and toxic behaviour
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Enforcement Responsibilities
Our project maintainers are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Maintainers have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
You can see a list of people who are recognized as "project maintainers" for Slimefun on the Slimefun GitHub organization:<br>
https://github.com/orgs/Slimefun/people
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders (labelled on Discord as "Admins" or "Moderators") responsible for enforcement on our [Discord Server](https://github.com/TheBusyBiscuit/Slimefun4#discord).
If you want your issue to be handled discreetly, message `TheBusyBiscuit#2610` or `Walshy#9709` privately on Discord and state your concerns.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Attribution
This Code of Conduct is a **modified version** of the original [Contributor Covenant Code of Conduct](https://www.contributor-covenant.org),
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
The Contributor Covenant was created by Coraline Ada Ehmke in 2014 and is released under the [CC BY 4.0 License](https://github.com/ContributorCovenant/contributor_covenant/blob/release/LICENSE.md).

View File

@ -1,37 +1,79 @@
# Slimefun Community Guidelines
Slimefun is a community project, everyone is welcome to open Issues, make Pull Requests or make Pull Requests for an opened Issue.
Without your help, this project is going to die.
## General Guidelines
Rules for all types of posts:
1. Follow our Templates for Issues and Pull Request, they are designed to tell you what exact Information we need and how you should present it to us.
2. Be nice and give constructive critism. Insulting, Harassment, Racism, Sexism or any form of bullying or discrimination is not tolerated.
3. Try to engage in conversations by pointing out scenarios to replicate Issues, providing fix approaches or other kind of help.
4. Advertisement is inappropriate and will be removed, especially advertisement for Minecraft Servers is completely unaccepted.
## GitHub Issues
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](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. 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 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.
## Pull Requests
Guidelines for making a Pull Request on GitHub:
1. Try to be reasonable with your additions. No, a Bacon flavoured unicorn that flies on a rainbow while dancing Gangnam Style is NOT a reasonable addition to this Project.
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")
# Contributing to Slimefun
This document outlines various ways how you can help contribute to Slimefun and make this a bigger and better project.<br>
All contributions must be inline with our [Code of Conduct](https://github.com/TheBusyBiscuit/Slimefun4/blob/master/.github/CODE_OF_CONDUCT.md) and [License](https://github.com/TheBusyBiscuit/Slimefun4/blob/master/LICENSE).
Please also follow the templates for Issues and Pull Requests we provide.
## 1. Issues: Bug Reports
One of the foundations for good software is reliability. To facilitate this reliability, our community must work together to crush bugs that arise.
This of course requires good information and knowledge about ongoing bugs and issues though.
You can help this project by reporting a bug on our [Issues Tracker](https://github.com/TheBusyBiscuit/Slimefun4/issues).<br>
Please adhere to the provided template and provide as much information as possible.
For more info on how to make good and helpful bug reports, check out our article on [How to report bugs](https://github.com/TheBusyBiscuit/Slimefun4/wiki/How-to-report-bugs).
If you encounter an issue which has already been reported, please don't open a new one.<br>
It would be awesome though if you could post a comment on the existing issue which explains how you were able to reproduce this yourself.
The more context and information we get, the easier we can fix it.
## 2. Pull Requests: Bug Fixes
Bugs that have been reported need to be fixed of course.<br>
Any open Issue on our [Issues Tracker](https://github.com/TheBusyBiscuit/Slimefun4/issues) is waiting to be fixed.
This is an Open-Source project and we love Pull Requests.
So if you have an idea on how to approach a known issue, feel free to make a [Pull Request](https://github.com/TheBusyBiscuit/Slimefun4/pulls) which fixes this bug.
You can also comment on the existing Issue, proposing your idea or communicating that you wanna work on this.
## 3. Pull Requests: Additions/Changes
Slimefun is an Open-Source project and anyone is allowed to make changes or add content to this plugin!
Please visit our [Discord Server](https://github.com/TheBusyBiscuit/Slimefun4#discord) and share your ideas first, we hate to reject changes because the community disagrees.<br>
So communicating your intended changes before-hand will ensure that you don't put too much work into something that might get rejected.
We also have a suggestions section in our Discord Server too. Suggestions can be placed in the `#suggestions` channel and community members can vote on a suggestion.
Suggestions which gotten enough votes will be moved to `#approved`.
Therefore our `#approved` is a great place to start looking for ideas on what to add or change, since it will definitely be something a large number of people agree with.
Also consider making an addon for your additions when they get too large, too abstract or too "niche".
You can check out our [Developer Guide](https://github.com/TheBusyBiscuit/Slimefun4/wiki/Developer-Guide) for a guide on how to create a Slimefun addon..
## 4. Pull Requests: Translations
Another great way to contribute to Slimefun is by working on translations for the project.
Slimefun's translation is available on [gitlocalize.com](https://gitlocalize.com/repo/3841).
Just find a language you are fluent in and translate away. But make sure to submit a "Review Request" when you are done.
One of our Language Moderators will review the changes and submit a Pull Request to the project for you.
#### Language Moderation
Very active community translators will have the option to become a "Language Moderator".
Language Moderators are responsible for proof-reading any new translations for their designated language and correct it when they see a mistake.
For more info on how or what to translate, check out our article on [How to translate Slimefun](https://github.com/TheBusyBiscuit/Slimefun4/wiki/Translating-Slimefun).
## 5. Pull Requests: Wiki contributions
Slimefun is a very large project and might be quite intimidating for new players.
That's why good documentation is always nice and helpful.
If you have played with Slimefun for a while and gotten yourself familiar with how things work, please consider contributing your experiences and knowledge to others via the wiki!
It would help out a lot :heart:
You can find a tutorial on how to contribute to our wiki right here:<br>
https://github.com/TheBusyBiscuit/Slimefun4/wiki/Expanding-the-Wiki
## 6. Pull Requests: Code Quality
Slimefun uses [sonarcloud.io](https://sonarcloud.io/dashboard?id=TheBusyBiscuit_Slimefun4) to monitor Code Quality.
We always welcome quality improvements to the code and the "Code Smells" section on [sonarcloud.io](https://sonarcloud.io/dashboard?id=TheBusyBiscuit_Slimefun4) is a great place to start.
But please keep in mind that some design patterns may not be changed too abruptly if an addon depends on them.
To prevent any accidents from happening, please contact us on our [Discord Server](https://github.com/TheBusyBiscuit/Slimefun4#discord) before-hand and state your intended changes.
#### Documentation
Code documentation is also a great way to improve the maintainability of the project.
Every class and every public method should have a Javadocs tag assigned to it.
Classes should also include an "author" tag to indicate who worked on that class.
Feel free to visit our [Javadocs](https://slimefun.github.io/javadocs/Slimefun4/docs/overview-summary.html)
#### Unit Tests
Unit Tests help us test the project to work as intended in an automated manner.<br>
More or better Unit Tests are always good to have, so feel free to submit a Test and place it in our [src/test/java](https://github.com/TheBusyBiscuit/Slimefun4/tree/master/src/test/java/io/github/thebusybiscuit/slimefun4/testing) directory
We are using [Junit 5 - Jupiter](https://github.com/junit-team/junit5/) and [MockBukkit](https://github.com/seeseemelk/MockBukkit) as our testing environment.<br>
Every new Unit Test should have a "DisplayName" annotation with a plain text description on what the Unit Test tests.

View File

@ -55,6 +55,9 @@
* Small performance improvements for Reactors
* Electric machines now show their tier in the Inventory name too
* Removed "Fuel efficiency" attribute for androids, since that was pretty much always at 1.0 anyway...
* Performance improvements for energy networks
* (API) Rewritten Block-Energy API
* Removed "durability" setting from cargo nodes
#### Fixes
* Fixed Programmable Androids rotating in the wrong direction
@ -91,6 +94,13 @@
* Fixed Fluid Pump treating low-level fluids like stationary fluids
* Fixed Fluid Pump not working on Bubble Columns
* Fixed #2251
* Fixed #2257
* Fixed #2260
* Fixed #2263
* Fixed #2265
* Fixed #2269
* Fixed #2266
* Fixed #2275
## Release Candidate 15 (01 Aug 2020)

11
pom.xml
View File

@ -294,7 +294,14 @@
<scope>provided</scope>
</dependency>
<!-- Development / Testing dependencies -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
@ -310,7 +317,7 @@
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.5.7</version>
<version>3.5.9</version>
<scope>test</scope>
</dependency>
@ -318,7 +325,7 @@
<dependency>
<groupId>com.github.TheBusyBiscuit</groupId>
<artifactId>CS-CoreLib2</artifactId>
<version>0.25</version>
<version>0.25.1</version>
<scope>compile</scope>
</dependency>
<dependency>

View File

@ -80,7 +80,7 @@ public class SlimefunRegistry {
private final Map<String, BlockInfoConfig> chunks = new HashMap<>();
private final Map<SlimefunGuideLayout, SlimefunGuideImplementation> layouts = new EnumMap<>(SlimefunGuideLayout.class);
private final Map<EntityType, Set<ItemStack>> mobDrops = new EnumMap<>(EntityType.class);
private final Map<String, Integer> capacities = new HashMap<>();
private final Map<String, BlockMenuPreset> blockMenuPresets = new HashMap<>();
private final Map<String, UniversalBlockMenu> universalInventories = new HashMap<>();
private final Map<Class<? extends ItemHandler>, Set<ItemHandler>> globalItemHandlers = new HashMap<>();
@ -234,10 +234,6 @@ public class SlimefunRegistry {
return slimefunIds;
}
public Map<String, Integer> getEnergyCapacities() {
return capacities;
}
public Map<String, BlockMenuPreset> getMenuPresets() {
return blockMenuPresets;
}

View File

@ -1,8 +1,15 @@
package io.github.thebusybiscuit.slimefun4.core.attributes;
import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNet;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.Capacitor;
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
/**
* This Interface, when attached to a class that inherits from {@link SlimefunItem}, marks
@ -36,4 +43,109 @@ public interface EnergyNetComponent extends ItemAttribute {
*/
int getCapacity();
/**
* This returns whether this {@link EnergyNetComponent} can hold energy charges.
* It returns true if {@link #getCapacity()} returns a number greater than zero.
*
* @return Whether this {@link EnergyNetComponent} can store energy.
*/
default boolean isChargeable() {
return getCapacity() > 0;
}
/**
* This returns the currently stored charge at a given {@link Location}.
*
* @param l
* The target {@link Location}
*
* @return The charge stored at that {@link Location}
*/
default int getCharge(Location l) {
Validate.notNull(l, "Location was null!");
String charge = BlockStorage.getLocationInfo(l, "energy-charge");
if (charge != null) {
return Integer.parseInt(charge);
}
else {
return 0;
}
}
/**
* This method sets the charge which is stored at a given {@link Location}
* If this {@link EnergyNetComponent} is of type {@code EnergyNetComponentType.CAPACITOR}, then
* this method will automatically update the texture of this {@link Capacitor} as well.
*
* @param l
* The target {@link Location}
* @param charge
* The new charge
*/
default void setCharge(Location l, int charge) {
Validate.notNull(l, "Location was null!");
Validate.isTrue(charge >= 0, "You can only set a charge of zero or more!");
int capacity = getCapacity();
// This method only makes sense if we can actually store energy
if (capacity > 0) {
charge = NumberUtils.clamp(0, charge, capacity);
// Do we even need to update the value?
if (charge != getCharge(l)) {
BlockStorage.addBlockInfo(l, "energy-charge", String.valueOf(charge), false);
// Update the capacitor texture
if (getEnergyComponentType() == EnergyNetComponentType.CAPACITOR) {
SlimefunUtils.updateCapacitorTexture(l, charge, capacity);
}
}
}
}
default void addCharge(Location l, int charge) {
Validate.notNull(l, "Location was null!");
Validate.isTrue(charge > 0, "You can only add a positive charge!");
int capacity = getCapacity();
// This method only makes sense if we can actually store energy
if (capacity > 0) {
int currentCharge = getCharge(l);
// Check if there is even space for new energy
if (currentCharge < capacity) {
int newCharge = Math.min(capacity, currentCharge + charge);
BlockStorage.addBlockInfo(l, "energy-charge", String.valueOf(newCharge), false);
// Update the capacitor texture
if (getEnergyComponentType() == EnergyNetComponentType.CAPACITOR) {
SlimefunUtils.updateCapacitorTexture(l, charge, capacity);
}
}
}
}
default void removeCharge(Location l, int charge) {
Validate.notNull(l, "Location was null!");
Validate.isTrue(charge > 0, "The charge to remove must be greater than zero!");
int capacity = getCapacity();
// This method only makes sense if we can actually store energy
if (capacity > 0) {
int currentCharge = getCharge(l);
// Check if there is even energy stored
if (currentCharge > 0) {
int newCharge = Math.max(0, currentCharge - charge);
BlockStorage.addBlockInfo(l, "energy-charge", String.valueOf(newCharge), false);
// Update the capacitor texture
if (getEnergyComponentType() == EnergyNetComponentType.CAPACITOR) {
SlimefunUtils.updateCapacitorTexture(l, charge, capacity);
}
}
}
}
}

View File

@ -4,6 +4,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nonnull;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.World;
@ -62,7 +64,7 @@ public abstract class MultiBlockMachine extends SlimefunItem implements NotPlace
this(category, item, recipe, new ItemStack[0], trigger);
}
protected void registerDefaultRecipes(List<ItemStack> recipes) {
protected void registerDefaultRecipes(@Nonnull List<ItemStack> recipes) {
// Override this method to register some default recipes
}
@ -87,7 +89,7 @@ public abstract class MultiBlockMachine extends SlimefunItem implements NotPlace
}
@Override
public void register(SlimefunAddon addon) {
public void register(@Nonnull SlimefunAddon addon) {
addItemHandler(getInteractionHandler());
super.register(addon);
}

View File

@ -25,7 +25,6 @@ import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
/**
* The {@link EnergyNet} is an implementation of {@link Network} that deals with
@ -44,38 +43,9 @@ public class EnergyNet extends Network {
private static final int RANGE = 6;
public static EnergyNetComponentType getComponent(Location l) {
String id = BlockStorage.checkID(l);
if (id == null) {
return EnergyNetComponentType.NONE;
}
SlimefunItem item = SlimefunItem.getByID(id);
if (item instanceof EnergyNetComponent) {
return ((EnergyNetComponent) item).getEnergyComponentType();
}
return EnergyNetComponentType.NONE;
}
public static EnergyNet getNetworkFromLocationOrCreate(Location l) {
Optional<EnergyNet> cargoNetwork = SlimefunPlugin.getNetworkManager().getNetworkFromLocation(l, EnergyNet.class);
if (cargoNetwork.isPresent()) {
return cargoNetwork.get();
}
else {
EnergyNet network = new EnergyNet(l);
SlimefunPlugin.getNetworkManager().registerNetwork(network);
return network;
}
}
private final Set<Location> generators = new HashSet<>();
private final Set<Location> storage = new HashSet<>();
private final Set<Location> consumers = new HashSet<>();
private final Map<Location, EnergyNetProvider> generators = new HashMap<>();
private final Map<Location, EnergyNetComponent> capacitors = new HashMap<>();
private final Map<Location, EnergyNetComponent> consumers = new HashMap<>();
protected EnergyNet(Location l) {
super(SlimefunPlugin.getNetworkManager(), l);
@ -92,15 +62,22 @@ public class EnergyNet extends Network {
return NetworkComponent.REGULATOR;
}
switch (getComponent(l)) {
case CAPACITOR:
return NetworkComponent.CONNECTOR;
case CONSUMER:
case GENERATOR:
return NetworkComponent.TERMINUS;
default:
EnergyNetComponent component = getComponent(l);
if (component == null) {
return null;
}
else {
switch (component.getEnergyComponentType()) {
case CAPACITOR:
return NetworkComponent.CONNECTOR;
case CONSUMER:
case GENERATOR:
return NetworkComponent.TERMINUS;
default:
return null;
}
}
}
@Override
@ -110,18 +87,27 @@ public class EnergyNet extends Network {
consumers.remove(l);
}
switch (getComponent(l)) {
case CAPACITOR:
storage.add(l);
break;
case CONSUMER:
consumers.add(l);
break;
case GENERATOR:
generators.add(l);
break;
default:
break;
EnergyNetComponent component = getComponent(l);
if (component != null) {
switch (component.getEnergyComponentType()) {
case CAPACITOR:
capacitors.put(l, component);
break;
case CONSUMER:
consumers.put(l, component);
break;
case GENERATOR:
if (component instanceof EnergyNetProvider) {
generators.put(l, (EnergyNetProvider) component);
}
else if (component instanceof SlimefunItem) {
((SlimefunItem) component).warn("This Item is marked as a GENERATOR but does not implement the interface EnergyNetProvider!");
}
break;
default:
break;
}
}
}
@ -130,6 +116,7 @@ public class EnergyNet extends Network {
if (!regulator.equals(b.getLocation())) {
SimpleHologram.update(b, "&4Multiple Energy Regulators connected");
SlimefunPlugin.getProfiler().closeEntry(b.getLocation(), SlimefunItems.ENERGY_REGULATOR.getItem(), timestamp.get());
return;
}
@ -139,14 +126,15 @@ public class EnergyNet extends Network {
SimpleHologram.update(b, "&4No Energy Network found");
}
else {
Map<Location, Integer> generatorsWithCapacity = new HashMap<>();
int supply = tickAllGenerators(generatorsWithCapacity, timestamp::getAndAdd) + tickAllCapacitors();
int supply = tickAllGenerators(timestamp::getAndAdd) + tickAllCapacitors();
int remainingEnergy = supply;
int demand = 0;
for (Location machine : consumers) {
int capacity = ChargableBlock.getMaxCharge(machine);
int charge = ChargableBlock.getCharge(machine);
for (Map.Entry<Location, EnergyNetComponent> entry : consumers.entrySet()) {
Location loc = entry.getKey();
EnergyNetComponent component = entry.getValue();
int capacity = component.getCapacity();
int charge = component.getCharge(loc);
if (charge < capacity) {
int availableSpace = capacity - charge;
@ -154,18 +142,18 @@ public class EnergyNet extends Network {
if (remainingEnergy > 0) {
if (remainingEnergy > availableSpace) {
ChargableBlock.setUnsafeCharge(machine, capacity, false);
component.setCharge(loc, capacity);
remainingEnergy -= availableSpace;
}
else {
ChargableBlock.setUnsafeCharge(machine, charge + remainingEnergy, false);
component.setCharge(loc, charge + remainingEnergy);
remainingEnergy = 0;
}
}
}
}
storeExcessEnergy(generatorsWithCapacity, remainingEnergy);
storeRemainingEnergy(remainingEnergy);
updateHologram(b, supply, demand);
}
@ -173,104 +161,99 @@ public class EnergyNet extends Network {
SlimefunPlugin.getProfiler().closeEntry(b.getLocation(), SlimefunItems.ENERGY_REGULATOR.getItem(), timestamp.get());
}
private void storeExcessEnergy(Map<Location, Integer> generators, int available) {
for (Location capacitor : storage) {
if (available > 0) {
int capacity = ChargableBlock.getMaxCharge(capacitor);
private void storeRemainingEnergy(int remainingEnergy) {
for (Map.Entry<Location, EnergyNetComponent> entry : capacitors.entrySet()) {
Location loc = entry.getKey();
EnergyNetComponent component = entry.getValue();
if (available > capacity) {
ChargableBlock.setUnsafeCharge(capacitor, capacity, true);
available -= capacity;
if (remainingEnergy > 0) {
int capacity = component.getCapacity();
if (remainingEnergy > capacity) {
component.setCharge(loc, capacity);
remainingEnergy -= capacity;
}
else {
ChargableBlock.setUnsafeCharge(capacitor, available, true);
available = 0;
component.setCharge(loc, remainingEnergy);
remainingEnergy = 0;
}
}
else {
ChargableBlock.setUnsafeCharge(capacitor, 0, true);
component.setCharge(loc, 0);
}
}
for (Map.Entry<Location, Integer> entry : generators.entrySet()) {
Location generator = entry.getKey();
int capacity = entry.getValue();
for (Map.Entry<Location, EnergyNetProvider> entry : generators.entrySet()) {
Location loc = entry.getKey();
EnergyNetProvider component = entry.getValue();
int capacity = component.getCapacity();
if (available > 0) {
if (available > capacity) {
ChargableBlock.setUnsafeCharge(generator, capacity, false);
available -= capacity;
if (remainingEnergy > 0) {
if (remainingEnergy > capacity) {
component.setCharge(loc, capacity);
remainingEnergy -= capacity;
}
else {
ChargableBlock.setUnsafeCharge(generator, available, false);
available = 0;
component.setCharge(loc, remainingEnergy);
remainingEnergy = 0;
}
}
else {
ChargableBlock.setUnsafeCharge(generator, 0, false);
component.setCharge(loc, 0);
}
}
}
private int tickAllGenerators(Map<Location, Integer> generatorsWithCapacity, LongConsumer timeCallback) {
Set<Location> exploded = new HashSet<>();
private int tickAllGenerators(LongConsumer timings) {
Set<Location> explodedBlocks = new HashSet<>();
int supply = 0;
for (Location source : generators) {
for (Map.Entry<Location, EnergyNetProvider> entry : generators.entrySet()) {
long timestamp = SlimefunPlugin.getProfiler().newEntry();
Config config = BlockStorage.getLocationInfo(source);
SlimefunItem item = SlimefunItem.getByID(config.getString("id"));
Location loc = entry.getKey();
EnergyNetProvider provider = entry.getValue();
SlimefunItem item = (SlimefunItem) provider;
if (item instanceof EnergyNetProvider) {
try {
EnergyNetProvider provider = (EnergyNetProvider) item;
int energy = provider.getGeneratedOutput(source, config);
try {
Config config = BlockStorage.getLocationInfo(loc);
int energy = provider.getGeneratedOutput(loc, config);
if (provider.getCapacity() > 0) {
generatorsWithCapacity.put(source, provider.getCapacity());
String charge = config.getString("energy-charge");
if (charge != null) {
energy += Integer.parseInt(charge);
}
}
if (provider.willExplode(source, config)) {
exploded.add(source);
BlockStorage.clearBlockInfo(source);
Slimefun.runSync(() -> {
source.getBlock().setType(Material.LAVA);
source.getWorld().createExplosion(source, 0F, false);
});
}
else {
supply += energy;
}
}
catch (Exception | LinkageError t) {
exploded.add(source);
new ErrorReport<>(t, source, item);
if (provider.isChargeable()) {
energy += provider.getCharge(loc);
}
long time = SlimefunPlugin.getProfiler().closeEntry(source, item, timestamp);
timeCallback.accept(time);
if (provider.willExplode(loc, config)) {
explodedBlocks.add(loc);
BlockStorage.clearBlockInfo(loc);
Slimefun.runSync(() -> {
loc.getBlock().setType(Material.LAVA);
loc.getWorld().createExplosion(loc, 0F, false);
});
}
else {
supply += energy;
}
}
else {
// This block seems to be gone now, better remove it to be extra safe
exploded.add(source);
catch (Exception | LinkageError t) {
explodedBlocks.add(loc);
new ErrorReport<>(t, loc, item);
}
long time = SlimefunPlugin.getProfiler().closeEntry(loc, item, timestamp);
timings.accept(time);
}
generators.removeAll(exploded);
// Remove all generators which have exploded
generators.keySet().removeAll(explodedBlocks);
return supply;
}
private int tickAllCapacitors() {
int supply = 0;
for (Location capacitor : storage) {
supply += ChargableBlock.getCharge(capacitor);
for (Map.Entry<Location, EnergyNetComponent> entry : capacitors.entrySet()) {
supply += entry.getValue().getCharge(entry.getKey());
}
return supply;
@ -286,4 +269,36 @@ public class EnergyNet extends Network {
SimpleHologram.update(b, "&2&l+ &a" + netGain + " &7J &e\u26A1");
}
}
private static EnergyNetComponent getComponent(Location l) {
SlimefunItem item = BlockStorage.check(l);
if (item instanceof EnergyNetComponent) {
return ((EnergyNetComponent) item);
}
return null;
}
/**
* This attempts to get an {@link EnergyNet} from a given {@link Location}.
* If no suitable {@link EnergyNet} could be found, a new one will be created.
*
* @param l
* The target {@link Location}
*
* @return The {@link EnergyNet} at that {@link Location}, or a new one
*/
public static EnergyNet getNetworkFromLocationOrCreate(Location l) {
Optional<EnergyNet> energyNetwork = SlimefunPlugin.getNetworkManager().getNetworkFromLocation(l, EnergyNet.class);
if (energyNetwork.isPresent()) {
return energyNetwork.get();
}
else {
EnergyNet network = new EnergyNet(l);
SlimefunPlugin.getNetworkManager().registerNetwork(network);
return network;
}
}
}

View File

@ -23,9 +23,9 @@ import net.md_5.bungee.api.chat.hover.content.Text;
class PerformanceSummary {
// The threshold at which a Block or Chunk is significant enough to appear in /sf timings
private static final int VISIBILITY_THRESHOLD = 300_000;
private static final int MIN_ITEMS = 4;
private static final int MAX_ITEMS = 12;
private static final int VISIBILITY_THRESHOLD = 260_000;
private static final int MIN_ITEMS = 6;
private static final int MAX_ITEMS = 20;
private final SlimefunProfiler profiler;
private final PerformanceRating rating;

View File

@ -709,7 +709,7 @@ public final class SlimefunItems {
public static final SlimefunItemStack GPS_GEO_SCANNER = new SlimefunItemStack("GPS_GEO_SCANNER", HeadTexture.GEO_SCANNER, "&bGPS Geo-Scanner", "", "&fScans a Chunk for natural Resources", "&fsuch as &8Oil");
public static final SlimefunItemStack PORTABLE_GEO_SCANNER = new SlimefunItemStack("PORTABLE_GEO_SCANNER", Material.CLOCK, "&bPortable Geo-Scanner", "", "&fScans a Chunk for natural Resources", "", "&eRight Click&7 to scan");
public static final SlimefunItemStack GEO_MINER = new SlimefunItemStack("GEO_MINER", HeadTexture.GEO_MINER, "&6GEO Miner", "", "&eMines up resources from the chunk", "&eThese Resources cannot be mined with a pickaxe", "", LoreBuilder.machine(MachineTier.ADVANCED, MachineType.MACHINE), LoreBuilder.speed(1), LoreBuilder.powerPerSecond(48), "", "&c&l! &cMake sure to Geo-Scan the Chunk first");
public static final SlimefunItemStack OIL_PUMP = new SlimefunItemStack("OIL_PUMP", HeadTexture.OIL_PUMP, "&fOil Pump", "", "&7Pumps up Oil and fills it into Buckets", "", "&c&l! &cMake sure to Geo-Scan the Chunk first");
public static final SlimefunItemStack OIL_PUMP = new SlimefunItemStack("OIL_PUMP", HeadTexture.OIL_PUMP, "&4Oil Pump", "", "&7Pumps up Oil and fills it into Buckets", "", "&c&l! &cMake sure to Geo-Scan the Chunk first");
public static final SlimefunItemStack OIL_BUCKET = new SlimefunItemStack("BUCKET_OF_OIL", HeadTexture.OIL_BUCKET, "&fBucket of Oil");
public static final SlimefunItemStack FUEL_BUCKET = new SlimefunItemStack("BUCKET_OF_FUEL", HeadTexture.FUEL_BUCKET, "&fBucket of Fuel");

View File

@ -112,19 +112,21 @@ public class AncientPedestal extends SlimefunItem {
public void placeItem(Player p, Block b) {
ItemStack hand = p.getInventory().getItemInMainHand();
ItemStack stack = new CustomItem(hand, ITEM_PREFIX + System.nanoTime());
stack.setAmount(1);
ItemStack displayItem = new CustomItem(hand, ITEM_PREFIX + System.nanoTime());
displayItem.setAmount(1);
// Get the display name of the original Item in the Player's hand
String nametag = ItemUtils.getItemName(hand);
if (p.getGameMode() != GameMode.CREATIVE) {
ItemUtils.consumeItem(hand, false);
}
String nametag = ItemUtils.getItemName(stack);
Item entity = b.getWorld().dropItem(b.getLocation().add(0.5, 1.2, 0.5), stack);
Item entity = b.getWorld().dropItem(b.getLocation().add(0.5, 1.2, 0.5), displayItem);
entity.setVelocity(new Vector(0, 0.1, 0));
SlimefunUtils.markAsNoPickup(entity, "altar_item");
entity.setCustomNameVisible(true);
entity.setCustomName(nametag);
SlimefunUtils.markAsNoPickup(entity, "altar_item");
p.playSound(b.getLocation(), Sound.ENTITY_ITEM_PICKUP, 0.3F, 0.3F);
}

View File

@ -27,6 +27,8 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class HologramProjector extends SlimefunItem {
private static final String OFFSET_PARAMETER = "offset";
public HologramProjector(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
super(category, item, recipeType, recipe, recipeOutput);
@ -40,7 +42,7 @@ public class HologramProjector extends SlimefunItem {
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, OFFSET_PARAMETER, "0.5");
BlockStorage.addBlockInfo(b, "owner", e.getPlayer().getUniqueId().toString());
getArmorStand(b, true);
@ -87,14 +89,14 @@ public class HologramProjector extends SlimefunItem {
return false;
});
menu.addItem(1, new CustomItem(Material.CLOCK, "&7Offset: &e" + DoubleHandler.fixDouble(Double.valueOf(BlockStorage.getLocationInfo(projector.getLocation(), "offset")) + 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_PARAMETER)) + 1.0D), "", "&rLeft Click: &7+0.1", "&rRight Click: &7-0.1"));
menu.addMenuClickHandler(1, (pl, slot, item, action) -> {
double offset = DoubleHandler.fixDouble(Double.valueOf(BlockStorage.getLocationInfo(projector.getLocation(), "offset")) + (action.isRightClicked() ? -0.1F : 0.1F));
double offset = DoubleHandler.fixDouble(Double.valueOf(BlockStorage.getLocationInfo(projector.getLocation(), OFFSET_PARAMETER)) + (action.isRightClicked() ? -0.1F : 0.1F));
ArmorStand hologram = getArmorStand(projector, true);
Location l = new Location(projector.getWorld(), projector.getX() + 0.5, projector.getY() + offset, projector.getZ() + 0.5);
hologram.teleport(l);
BlockStorage.addBlockInfo(projector, "offset", String.valueOf(offset));
BlockStorage.addBlockInfo(projector, OFFSET_PARAMETER, String.valueOf(offset));
openEditor(pl, projector);
return false;
});
@ -104,12 +106,16 @@ public class HologramProjector extends SlimefunItem {
private static ArmorStand getArmorStand(Block projector, boolean createIfNoneExists) {
String nametag = BlockStorage.getLocationInfo(projector.getLocation(), "text");
double offset = Double.parseDouble(BlockStorage.getLocationInfo(projector.getLocation(), "offset"));
double offset = Double.parseDouble(BlockStorage.getLocationInfo(projector.getLocation(), OFFSET_PARAMETER));
Location l = new Location(projector.getWorld(), projector.getX() + 0.5, projector.getY() + offset, projector.getZ() + 0.5);
for (Entity n : l.getChunk().getEntities()) {
if (n instanceof ArmorStand && n.getCustomName() != null && n.getCustomName().equals(nametag) && l.distanceSquared(n.getLocation()) < 0.4D) {
return (ArmorStand) n;
if (n instanceof ArmorStand && l.distanceSquared(n.getLocation()) < 0.4) {
String customName = n.getCustomName();
if (customName != null && customName.equals(nametag)) {
return (ArmorStand) n;
}
}
}

View File

@ -1,5 +1,7 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.blocks;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Locale;
import java.util.Optional;
@ -77,5 +79,12 @@ public class RepairedSpawner extends SimpleSlimefunItem<BlockPlaceHandler> {
return Optional.empty();
}
@Override
public Collection<ItemStack> getDrops() {
// There should be no drops by default since drops are handled by the
// Pickaxe of Containment exclusively.
return new ArrayList<>();
}
}

View File

@ -13,7 +13,7 @@ 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 io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -77,29 +77,28 @@ abstract class AbstractCargoNode extends SlimefunItem {
protected void addChannelSelector(Block b, BlockMenu menu, int slotPrev, int slotCurrent, int slotNext) {
boolean isChestTerminalInstalled = SlimefunPlugin.getThirdPartySupportService().isChestTerminalInstalled();
int channel = getSelectedChannel(b);
menu.replaceExistingItem(slotPrev, new CustomItem(SlimefunUtils.getCustomHead(HeadTexture.CARGO_ARROW_LEFT.getTexture()), "&bPrevious Channel", "", "&e> Click to decrease the Channel ID by 1"));
menu.replaceExistingItem(slotPrev, new CustomItem(HeadTexture.CARGO_ARROW_LEFT.getAsItemStack(), "&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;
int newChannel = channel - 1;
if (channel < 0) {
if (isChestTerminalInstalled) {
channel = 16;
newChannel = 16;
}
else {
channel = 15;
newChannel = 15;
}
}
BlockStorage.addBlockInfo(b, FREQUENCY, String.valueOf(channel));
BlockStorage.addBlockInfo(b, FREQUENCY, String.valueOf(newChannel));
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.replaceExistingItem(slotCurrent, new CustomItem(HeadTexture.CHEST_TERMINAL.getAsItemStack(), "&bChannel ID: &3" + (channel + 1)));
menu.addMenuClickHandler(slotCurrent, ChestMenuUtils.getEmptyClickHandler());
}
else {
@ -107,25 +106,42 @@ abstract class AbstractCargoNode extends SlimefunItem {
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.replaceExistingItem(slotNext, new CustomItem(HeadTexture.CARGO_ARROW_RIGHT.getAsItemStack(), "&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;
int newChannel = channel + 1;
if (isChestTerminalInstalled) {
if (channeln > 16) {
channeln = 0;
if (newChannel > 16) {
newChannel = 0;
}
}
else if (channeln > 15) {
channeln = 0;
else if (newChannel > 15) {
newChannel = 0;
}
BlockStorage.addBlockInfo(b, FREQUENCY, String.valueOf(channeln));
BlockStorage.addBlockInfo(b, FREQUENCY, String.valueOf(newChannel));
updateBlockMenu(menu, b);
return false;
});
}
private int getSelectedChannel(Block b) {
if (!BlockStorage.hasBlockInfo(b)) {
return 0;
}
else {
String frequency = BlockStorage.getLocationInfo(b.getLocation(), FREQUENCY);
if (frequency == null) {
return 0;
}
else {
int channel = Integer.parseInt(frequency);
return NumberUtils.clamp(0, channel, 16);
}
}
}
protected abstract void onPlace(BlockPlaceEvent e);
protected abstract void createBorder(BlockMenuPreset preset);

View File

@ -3,10 +3,7 @@ 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;
@ -29,6 +26,8 @@ import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
abstract class AbstractFilterNode extends AbstractCargoNode {
protected static final int[] SLOTS = { 19, 20, 21, 28, 29, 30, 37, 38, 39 };
private static final String FILTER_TYPE = "filter-type";
private static final String FILTER_LORE = "filter-lore";
public AbstractFilterNode(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
super(category, item, recipeType, recipe, recipeOutput);
@ -50,8 +49,8 @@ abstract class AbstractFilterNode extends AbstractCargoNode {
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_TYPE, "whitelist");
BlockStorage.addBlockInfo(b, FILTER_LORE, String.valueOf(true));
BlockStorage.addBlockInfo(b, "filter-durability", String.valueOf(false));
}
@ -66,12 +65,12 @@ abstract class AbstractFilterNode extends AbstractCargoNode {
@Override
protected void updateBlockMenu(BlockMenu menu, Block b) {
String filterType = BlockStorage.getLocationInfo(b.getLocation(), "filter-type");
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");
BlockStorage.addBlockInfo(b, FILTER_TYPE, "blacklist");
updateBlockMenu(menu, b);
return false;
});
@ -79,48 +78,18 @@ abstract class AbstractFilterNode extends AbstractCargoNode {
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");
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");
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));
BlockStorage.addBlockInfo(b, FILTER_LORE, String.valueOf(false));
updateBlockMenu(menu, b);
return false;
});
@ -128,7 +97,7 @@ abstract class AbstractFilterNode extends AbstractCargoNode {
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));
BlockStorage.addBlockInfo(b, FILTER_LORE, String.valueOf(true));
updateBlockMenu(menu, b);
return false;
});

View File

@ -8,7 +8,7 @@ import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
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[] BORDER = { 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 22, 23, 24, 26, 27, 31, 32, 33, 34, 35, 36, 40, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 };
public AdvancedCargoOutputNode(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe, null);

View File

@ -6,7 +6,6 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
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.api.BlockStorage;
@ -15,7 +14,8 @@ import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
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[] BORDER = { 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 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 String ROUND_ROBIN_MODE = "round-robin";
public CargoInputNode(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, ItemStack recipeOutput) {
super(category, item, recipeType, recipe, recipeOutput);
@ -29,26 +29,26 @@ public class CargoInputNode extends AbstractFilterNode {
@Override
protected void onPlace(BlockPlaceEvent e) {
super.onPlace(e);
BlockStorage.addBlockInfo(e.getBlock(), "round-robin", String.valueOf(false));
BlockStorage.addBlockInfo(e.getBlock(), ROUND_ROBIN_MODE, String.valueOf(false));
}
@Override
protected void updateBlockMenu(BlockMenu menu, Block b) {
super.updateBlockMenu(menu, b);
String roundRobinMode = BlockStorage.getLocationInfo(b.getLocation(), "round-robin");
String roundRobinMode = BlockStorage.getLocationInfo(b.getLocation(), ROUND_ROBIN_MODE);
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.replaceExistingItem(24, new CustomItem(HeadTexture.ENERGY_REGULATOR.getAsItemStack(), "&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));
BlockStorage.addBlockInfo(b, ROUND_ROBIN_MODE, String.valueOf(true));
updateBlockMenu(menu, b);
return false;
});
}
else {
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.replaceExistingItem(24, new CustomItem(HeadTexture.ENERGY_REGULATOR.getAsItemStack(), "&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));
BlockStorage.addBlockInfo(b, ROUND_ROBIN_MODE, String.valueOf(false));
updateBlockMenu(menu, b);
return false;
});

View File

@ -50,6 +50,7 @@ public class EnergyRegulator extends SlimefunItem {
@Override
public void preRegister() {
addItemHandler(onPlace());
addItemHandler(new BlockTicker() {
@Override
@ -65,7 +66,8 @@ public class EnergyRegulator extends SlimefunItem {
}
private void tick(Block b) {
EnergyNet.getNetworkFromLocationOrCreate(b.getLocation()).tick(b);
EnergyNet network = EnergyNet.getNetworkFromLocationOrCreate(b.getLocation());
network.tick(b);
}
}

View File

@ -2,19 +2,30 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.electric.gadgets
import java.util.Optional;
import org.bukkit.block.Block;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.math.DoubleHandler;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNet;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
/**
* The {@link Multimeter} is used to measure charge and capacity of any {@link EnergyNetComponent}.
*
* @author TheBusyBiscuit
*
* @see EnergyNet
* @see EnergyNetComponent
*
*/
public class Multimeter extends SimpleSlimefunItem<ItemUseHandler> {
public Multimeter(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
@ -24,21 +35,26 @@ public class Multimeter extends SimpleSlimefunItem<ItemUseHandler> {
@Override
public ItemUseHandler getItemHandler() {
return e -> {
Optional<Block> block = e.getClickedBlock();
Optional<SlimefunItem> block = e.getSlimefunBlock();
if (block.isPresent()) {
Block b = block.get();
if (e.getClickedBlock().isPresent() && block.isPresent()) {
SlimefunItem item = block.get();
if (ChargableBlock.isChargable(b)) {
e.cancel();
if (item instanceof EnergyNetComponent) {
EnergyNetComponent component = (EnergyNetComponent) item;
String stored = DoubleHandler.getFancyDouble(ChargableBlock.getCharge(b)) + " J";
String capacity = DoubleHandler.getFancyDouble(ChargableBlock.getMaxCharge(b)) + " J";
if (component.isChargeable()) {
e.cancel();
Player p = e.getPlayer();
p.sendMessage("");
SlimefunPlugin.getLocalization().sendMessage(p, "messages.multimeter", false, str -> str.replace("%stored%", stored).replace("%capacity%", capacity));
p.sendMessage("");
Location l = e.getClickedBlock().get().getLocation();
String stored = DoubleHandler.getFancyDouble(component.getCharge(l)) + " J";
String capacity = DoubleHandler.getFancyDouble(component.getCapacity()) + " J";
Player p = e.getPlayer();
p.sendMessage("");
SlimefunPlugin.getLocalization().sendMessage(p, "messages.multimeter", false, str -> str.replace("%stored%", stored).replace("%capacity%", capacity));
p.sendMessage("");
}
}
}
};

View File

@ -8,13 +8,26 @@ import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetProvider;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNet;
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.api.SlimefunItemStack;
/**
* The {@link SolarGenerator} is a simple {@link EnergyNetProvider} which generates energy if
* it has direct contact with sunlight.
*
* Some versions of the {@link SolarGenerator} will even generate energy at night, this is determined by
* {@link #getNightEnergy()}.
*
* @author TheBusyBiscuit
*
* @see EnergyNet
* @see EnergyNetProvider
*
*/
public class SolarGenerator extends SlimefunItem implements EnergyNetProvider {
private final int dayEnergy;
@ -47,11 +60,6 @@ public class SolarGenerator extends SlimefunItem implements EnergyNetProvider {
return nightEnergy;
}
@Override
public EnergyNetComponentType getEnergyComponentType() {
return EnergyNetComponentType.GENERATOR;
}
@Override
public int getCapacity() {
return 0;
@ -64,23 +72,20 @@ public class SolarGenerator extends SlimefunItem implements EnergyNetProvider {
if (world.getEnvironment() != Environment.NORMAL) {
return 0;
}
else {
boolean isDaytime = isDaytime(world);
boolean isDaytime = isDaytime(world);
// Performance optimization for daytime-only solar generators
if (!isDaytime && getNightEnergy() < 0.1) {
return 0;
// Performance optimization for daytime-only solar generators
if (!isDaytime && getNightEnergy() < 1) {
return 0;
}
else if (!world.isChunkLoaded(l.getBlockX() >> 4, l.getBlockZ() >> 4) || l.getBlock().getLightFromSky() < 15) {
return 0;
}
else {
return isDaytime ? getDayEnergy() : getNightEnergy();
}
}
if (!world.isChunkLoaded(l.getBlockX() >> 4, l.getBlockZ() >> 4) || l.getBlock().getLightFromSky() != 15) {
return 0;
}
if (isDaytime) {
return getDayEnergy();
}
return getNightEnergy();
}
/**
@ -93,7 +98,8 @@ public class SolarGenerator extends SlimefunItem implements EnergyNetProvider {
* @return Whether the given {@link World} has daytime and no active thunderstorm
*/
private boolean isDaytime(World world) {
return !world.hasStorm() && !world.isThundering() && (world.getTime() < 12300 || world.getTime() > 23850);
long time = world.getTime();
return !world.hasStorm() && !world.isThundering() && (time < 12300 || time > 23850);
}
@Override

View File

@ -30,7 +30,6 @@ import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
@ -195,7 +194,7 @@ public abstract class AbstractEntityAssembler<T extends Entity> extends SimpleSl
return;
}
if (lifetime % 60 == 0 && ChargableBlock.getCharge(b) >= getEnergyConsumption()) {
if (lifetime % 60 == 0 && getCharge(b.getLocation()) >= getEnergyConsumption()) {
BlockMenu menu = BlockStorage.getInventory(b);
boolean hasBody = findResource(menu, getBody(), bodySlots);
@ -204,7 +203,7 @@ public abstract class AbstractEntityAssembler<T extends Entity> extends SimpleSl
if (hasBody && hasHead) {
consumeResources(menu);
ChargableBlock.addCharge(b, -getEnergyConsumption());
removeCharge(b.getLocation(), getEnergyConsumption());
double offset = Double.parseDouble(BlockStorage.getLocationInfo(b.getLocation(), KEY_OFFSET));
Slimefun.runSync(() -> {

View File

@ -0,0 +1,82 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
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.interfaces.InventoryBlock;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
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 abstract class AbstractGrowthAccelerator extends SlimefunItem implements InventoryBlock, EnergyNetComponent {
private static final int[] BORDER = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 };
public AbstractGrowthAccelerator(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
createPreset(this, this::constructMenu);
registerBlockHandler(getID(), (p, b, tool, reason) -> {
BlockMenu inv = BlockStorage.getInventory(b);
if (inv != null) {
inv.dropItems(b.getLocation(), getInputSlots());
}
return true;
});
}
private void constructMenu(BlockMenuPreset preset) {
for (int i : BORDER) {
preset.addItem(i, new CustomItem(Material.CYAN_STAINED_GLASS_PANE, " "), ChestMenuUtils.getEmptyClickHandler());
}
}
@Override
public EnergyNetComponentType getEnergyComponentType() {
return EnergyNetComponentType.CONSUMER;
}
@Override
public int[] getInputSlots() {
return new int[] { 10, 11, 12, 13, 14, 15, 16 };
}
@Override
public int[] getOutputSlots() {
return new int[0];
}
@Override
public void preRegister() {
super.preRegister();
addItemHandler(new BlockTicker() {
@Override
public void tick(Block b, SlimefunItem sf, Config data) {
AbstractGrowthAccelerator.this.tick(b);
}
@Override
public boolean isSynchronized() {
return true;
}
});
}
protected abstract void tick(Block b);
}

View File

@ -1,6 +1,5 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.block.Block;
import org.bukkit.entity.Ageable;
@ -8,69 +7,25 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
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.interfaces.InventoryBlock;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
public class AnimalGrowthAccelerator extends SlimefunItem implements InventoryBlock, EnergyNetComponent {
private final int[] border = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 };
public class AnimalGrowthAccelerator extends AbstractGrowthAccelerator {
private static final int ENERGY_CONSUMPTION = 14;
private static final double RADIUS = 3.0;
// We wanna strip the Slimefun Item id here
private static final ItemStack organicFood = new ItemStackWrapper(SlimefunItems.ORGANIC_FOOD);
public AnimalGrowthAccelerator(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
createPreset(this, this::constructMenu);
registerBlockHandler(getID(), (p, b, tool, reason) -> {
BlockMenu inv = BlockStorage.getInventory(b);
if (inv != null) {
inv.dropItems(b.getLocation(), getInputSlots());
}
return true;
});
}
private void constructMenu(BlockMenuPreset preset) {
for (int i : border) {
preset.addItem(i, new CustomItem(new ItemStack(Material.CYAN_STAINED_GLASS_PANE), " "), ChestMenuUtils.getEmptyClickHandler());
}
}
@Override
public int[] getInputSlots() {
return new int[] { 10, 11, 12, 13, 14, 15, 16 };
}
@Override
public int[] getOutputSlots() {
return new int[0];
}
@Override
public EnergyNetComponentType getEnergyComponentType() {
return EnergyNetComponentType.CONSUMER;
}
@Override
@ -79,37 +34,23 @@ public class AnimalGrowthAccelerator extends SlimefunItem implements InventoryBl
}
@Override
public void preRegister() {
addItemHandler(new BlockTicker() {
@Override
public void tick(Block b, SlimefunItem sf, Config data) {
AnimalGrowthAccelerator.this.tick(b);
}
@Override
public boolean isSynchronized() {
return true;
}
});
}
protected void tick(Block b) {
BlockMenu inv = BlockStorage.getInventory(b);
for (Entity n : b.getWorld().getNearbyEntities(b.getLocation(), 3.0, 3.0, 3.0, n -> n instanceof Ageable && n.isValid() && !((Ageable) n).isAdult())) {
for (Entity n : b.getWorld().getNearbyEntities(b.getLocation(), RADIUS, RADIUS, RADIUS, this::isReadyToGrow)) {
for (int slot : getInputSlots()) {
if (SlimefunUtils.isItemSimilar(inv.getItemInSlot(slot), organicFood, false)) {
if (ChargableBlock.getCharge(b) < ENERGY_CONSUMPTION) {
if (SlimefunUtils.isItemSimilar(inv.getItemInSlot(slot), organicFood, false, false)) {
if (getCharge(b.getLocation()) < ENERGY_CONSUMPTION) {
return;
}
ChargableBlock.addCharge(b, -ENERGY_CONSUMPTION);
Ageable ageable = (Ageable) n;
removeCharge(b.getLocation(), ENERGY_CONSUMPTION);
inv.consumeItem(slot);
((Ageable) n).setAge(((Ageable) n).getAge() + 2000);
ageable.setAge(ageable.getAge() + 2000);
if (((Ageable) n).getAge() > 0) {
((Ageable) n).setAge(0);
if (ageable.getAge() > 0) {
ageable.setAge(0);
}
n.getWorld().spawnParticle(Particle.VILLAGER_HAPPY, ((LivingEntity) n).getEyeLocation(), 8, 0.2F, 0.2F, 0.2F);
@ -119,4 +60,8 @@ public class AnimalGrowthAccelerator extends SlimefunItem implements InventoryBl
}
}
private boolean isReadyToGrow(Entity n) {
return n instanceof Ageable && n.isValid() && !((Ageable) n).isAdult();
}
}

View File

@ -1,33 +1,34 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines;
import org.bukkit.Material;
import org.bukkit.block.Block;
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.implementation.SlimefunItems;
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.SlimefunItem.abstractItems.AContainer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
/**
* The {@link AutoAnvil} is an electric machine which can repair any {@link ItemStack} using
* Duct tape.
*
* @author TheBusyBiscuit
*
*/
public abstract class AutoAnvil extends AContainer {
public AutoAnvil(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
}
private final int repairFactor;
@Override
public String getInventoryTitle() {
return "Auto-Anvil";
public AutoAnvil(Category category, int repairFactor, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
this.repairFactor = repairFactor;
}
@Override
@ -45,61 +46,32 @@ public abstract class AutoAnvil extends AContainer {
return "AUTO_ANVIL";
}
public abstract int getRepairFactor();
@Override
protected void tick(Block b) {
BlockMenu menu = BlockStorage.getInventory(b);
protected MachineRecipe findNextRecipe(BlockMenu menu) {
for (int slot : getInputSlots()) {
ItemStack ductTape = menu.getItemInSlot(slot == getInputSlots()[0] ? getInputSlots()[1] : getInputSlots()[0]);
ItemStack item = menu.getItemInSlot(slot);
if (isProcessing(b)) {
int timeleft = progress.get(b);
if (item != null && item.getType().getMaxDurability() > 0 && ((Damageable) item.getItemMeta()).getDamage() > 0) {
if (SlimefunUtils.isItemSimilar(ductTape, SlimefunItems.DUCT_TAPE, true, false)) {
ItemStack repairedItem = repair(item);
if (timeleft > 0) {
ChestMenuUtils.updateProgressbar(menu, 22, timeleft, processing.get(b).getTicks(), getProgressBar());
if (ChargableBlock.getCharge(b) < getEnergyConsumption()) {
return;
}
ChargableBlock.addCharge(b, -getEnergyConsumption());
progress.put(b, timeleft - 1);
}
else {
menu.replaceExistingItem(22, new CustomItem(new ItemStack(Material.BLACK_STAINED_GLASS_PANE), " "));
menu.pushItem(processing.get(b).getOutput()[0].clone(), getOutputSlots());
progress.remove(b);
processing.remove(b);
}
}
else {
MachineRecipe recipe = null;
for (int slot : getInputSlots()) {
ItemStack target = menu.getItemInSlot(slot == getInputSlots()[0] ? getInputSlots()[1] : getInputSlots()[0]);
ItemStack item = menu.getItemInSlot(slot);
if (item != null && item.getType().getMaxDurability() > 0 && ((Damageable) item.getItemMeta()).getDamage() > 0) {
if (SlimefunUtils.isItemSimilar(target, SlimefunItems.DUCT_TAPE, true)) {
ItemStack repaired = repair(item);
recipe = new MachineRecipe(30, new ItemStack[] { target, item }, new ItemStack[] { repaired });
if (!menu.fits(repairedItem, getOutputSlots())) {
return null;
}
break;
}
}
for (int inputSlot : getInputSlots()) {
menu.consumeItem(inputSlot);
}
if (recipe != null) {
if (!menu.fits(recipe.getOutput()[0], getOutputSlots())) return;
for (int slot : getInputSlots()) {
menu.consumeItem(slot);
return new MachineRecipe(30, new ItemStack[] { ductTape, item }, new ItemStack[] { repairedItem });
}
processing.put(b, recipe);
progress.put(b, recipe.getTicks());
break;
}
}
return null;
}
private ItemStack repair(ItemStack item) {
@ -107,7 +79,8 @@ public abstract class AutoAnvil extends AContainer {
ItemMeta meta = repaired.getItemMeta();
short maxDurability = item.getType().getMaxDurability();
short durability = (short) (((Damageable) meta).getDamage() - (maxDurability / getRepairFactor()));
int repairPercentage = 100 / repairFactor;
short durability = (short) (((Damageable) meta).getDamage() - (maxDurability / repairPercentage));
if (durability < 0) {
durability = 0;

View File

@ -22,7 +22,6 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
@ -90,6 +89,7 @@ public class AutoBreeder extends SlimefunItem implements InventoryBlock, EnergyN
public boolean isSynchronized() {
return true;
}
});
}
@ -99,11 +99,11 @@ public class AutoBreeder extends SlimefunItem implements InventoryBlock, EnergyN
for (Entity n : b.getWorld().getNearbyEntities(b.getLocation(), 4.0, 2.0, 4.0, this::canBreed)) {
for (int slot : getInputSlots()) {
if (SlimefunUtils.isItemSimilar(inv.getItemInSlot(slot), organicFood, false)) {
if (ChargableBlock.getCharge(b) < ENERGY_CONSUMPTION) {
if (getCharge(b.getLocation()) < ENERGY_CONSUMPTION) {
return;
}
ChargableBlock.addCharge(b, -ENERGY_CONSUMPTION);
removeCharge(b.getLocation(), ENERGY_CONSUMPTION);
inv.consumeItem(slot);
((Animals) n).setLoveModeTicks(600);

View File

@ -7,7 +7,6 @@ import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
@ -15,10 +14,8 @@ import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.Repairable;
import io.github.thebusybiscuit.cscorelib2.inventory.InvUtils;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.api.events.AutoDisenchantEvent;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import me.mrCookieSlime.EmeraldEnchants.EmeraldEnchants;
import me.mrCookieSlime.EmeraldEnchants.ItemEnchantment;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -26,9 +23,7 @@ import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
/**
@ -65,51 +60,7 @@ public class AutoDisenchanter extends AContainer {
}
@Override
protected void tick(Block b) {
BlockMenu menu = BlockStorage.getInventory(b);
if (isProcessing(b)) {
int timeleft = progress.get(b);
if (timeleft > 0) {
ChestMenuUtils.updateProgressbar(menu, 22, timeleft, processing.get(b).getTicks(), getProgressBar());
if (ChargableBlock.getCharge(b) < getEnergyConsumption()) {
return;
}
ChargableBlock.addCharge(b, -getEnergyConsumption());
progress.put(b, timeleft - 1);
}
else {
menu.replaceExistingItem(22, new CustomItem(Material.BLACK_STAINED_GLASS_PANE, " "));
for (ItemStack item : processing.get(b).getOutput()) {
menu.pushItem(item, getOutputSlots());
}
progress.remove(b);
processing.remove(b);
}
}
else {
MachineRecipe recipe = findRecipe(menu);
if (recipe != null) {
if (!InvUtils.fitAll(menu.toInventory(), recipe.getOutput(), getOutputSlots())) {
return;
}
for (int slot : getInputSlots()) {
menu.consumeItem(slot);
}
processing.put(b, recipe);
progress.put(b, recipe.getTicks());
}
}
}
private MachineRecipe findRecipe(BlockMenu menu) {
protected MachineRecipe findNextRecipe(BlockMenu menu) {
Map<Enchantment, Integer> enchantments = new HashMap<>();
Set<ItemEnchantment> emeraldEnchantments = new HashSet<>();
@ -157,7 +108,17 @@ public class AutoDisenchanter extends AContainer {
EmeraldEnchants.getInstance().getRegistry().applyEnchantment(disenchantedItem, ench.getEnchantment(), 0);
}
return new MachineRecipe(90 * amount, new ItemStack[] { target, item }, new ItemStack[] { disenchantedItem, book });
MachineRecipe recipe = new MachineRecipe(90 * amount, new ItemStack[] { target, item }, new ItemStack[] { disenchantedItem, book });
if (!InvUtils.fitAll(menu.toInventory(), recipe.getOutput(), getOutputSlots())) {
return null;
}
for (int inputSlot : getInputSlots()) {
menu.consumeItem(inputSlot);
}
return recipe;
}
}
}

View File

@ -6,15 +6,12 @@ import java.util.Map;
import java.util.Set;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import io.github.thebusybiscuit.cscorelib2.inventory.InvUtils;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import me.mrCookieSlime.EmeraldEnchants.EmeraldEnchants;
import me.mrCookieSlime.EmeraldEnchants.ItemEnchantment;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
@ -22,9 +19,7 @@ import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
public class AutoEnchanter extends AContainer {
@ -53,52 +48,7 @@ public class AutoEnchanter extends AContainer {
}
@Override
protected void tick(Block b) {
BlockMenu menu = BlockStorage.getInventory(b.getLocation());
if (isProcessing(b)) {
int timeleft = progress.get(b);
if (timeleft > 0) {
ChestMenuUtils.updateProgressbar(menu, 22, timeleft, processing.get(b).getTicks(), getProgressBar());
if (ChargableBlock.getCharge(b) < getEnergyConsumption()) {
return;
}
ChargableBlock.addCharge(b, -getEnergyConsumption());
progress.put(b, timeleft - 1);
}
else {
menu.replaceExistingItem(22, new CustomItem(new ItemStack(Material.BLACK_STAINED_GLASS_PANE), " "));
for (ItemStack item : processing.get(b).getOutput()) {
menu.pushItem(item, getOutputSlots());
}
progress.remove(b);
processing.remove(b);
}
}
else {
MachineRecipe recipe = findRecipe(menu);
if (recipe != null) {
if (!InvUtils.fitAll(menu.toInventory(), recipe.getOutput(), getOutputSlots())) {
return;
}
for (int slot : getInputSlots()) {
menu.consumeItem(slot);
}
processing.put(b, recipe);
progress.put(b, recipe.getTicks());
}
}
}
private MachineRecipe findRecipe(BlockMenu menu) {
protected MachineRecipe findNextRecipe(BlockMenu menu) {
for (int slot : getInputSlots()) {
ItemStack target = menu.getItemInSlot(slot == getInputSlots()[0] ? getInputSlots()[1] : getInputSlots()[0]);
@ -109,7 +59,6 @@ public class AutoEnchanter extends AContainer {
ItemStack item = menu.getItemInSlot(slot);
// Enchant
if (item != null && item.getType() == Material.ENCHANTED_BOOK && target != null) {
Map<Enchantment, Integer> enchantments = new HashMap<>();
Set<ItemEnchantment> emeraldEnchantments = new HashSet<>();
@ -132,6 +81,7 @@ public class AutoEnchanter extends AContainer {
emeraldEnchantments.add(enchantment);
}
}
specialAmount += EmeraldEnchants.getInstance().getRegistry().getEnchantments(target).size();
}
@ -147,7 +97,17 @@ public class AutoEnchanter extends AContainer {
EmeraldEnchants.getInstance().getRegistry().applyEnchantment(enchantedItem, ench.getEnchantment(), ench.getLevel());
}
return new MachineRecipe(75 * amount, new ItemStack[] { target, item }, new ItemStack[] { enchantedItem, new ItemStack(Material.BOOK) });
MachineRecipe recipe = new MachineRecipe(75 * amount, new ItemStack[] { target, item }, new ItemStack[] { enchantedItem, new ItemStack(Material.BOOK) });
if (!InvUtils.fitAll(menu.toInventory(), recipe.getOutput(), getOutputSlots())) {
return null;
}
for (int inputSlot : getInputSlots()) {
menu.consumeItem(inputSlot);
}
return recipe;
}
return null;

View File

@ -31,7 +31,6 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
@ -56,7 +55,7 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
@Override
public void newInstance(BlockMenu menu, Block b) {
if (!BlockStorage.hasBlockInfo(b) || BlockStorage.getLocationInfo(b.getLocation(), "enabled") == null || BlockStorage.getLocationInfo(b.getLocation(), "enabled").equals(String.valueOf(false))) {
menu.replaceExistingItem(6, new CustomItem(new ItemStack(Material.GUNPOWDER), "&7Enabled: &4\u2718", "", "&e> Click to enable this Machine"));
menu.replaceExistingItem(6, new CustomItem(Material.GUNPOWDER, "&7Enabled: &4\u2718", "", "&e> Click to enable this Machine"));
menu.addMenuClickHandler(6, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "enabled", String.valueOf(true));
newInstance(menu, b);
@ -64,7 +63,7 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
});
}
else {
menu.replaceExistingItem(6, new CustomItem(new ItemStack(Material.REDSTONE), "&7Enabled: &2\u2714", "", "&e> Click to disable this Machine"));
menu.replaceExistingItem(6, new CustomItem(Material.REDSTONE, "&7Enabled: &2\u2714", "", "&e> Click to disable this Machine"));
menu.addMenuClickHandler(6, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, "enabled", String.valueOf(false));
newInstance(menu, b);
@ -72,7 +71,7 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
});
}
menu.replaceExistingItem(7, new CustomItem(new ItemStack(Material.CRAFTING_TABLE), "&7Craft Last", "", "&e> Click to craft the last shaped recipe", "&cOnly works with the last one"));
menu.replaceExistingItem(7, new CustomItem(Material.CRAFTING_TABLE, "&7Craft Last", "", "&e> Click to craft the last shaped recipe", "&cOnly works with the last one"));
menu.addMenuClickHandler(7, (p, slot, item, action) -> {
tick(b, true);
return false;
@ -215,7 +214,7 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
return;
}
if (ChargableBlock.getCharge(block) < getEnergyConsumption()) {
if (getCharge(block.getLocation()) < getEnergyConsumption()) {
return;
}
@ -259,7 +258,7 @@ public abstract class AutomatedCraftingChamber extends SlimefunItem implements I
ItemStack output = SlimefunPlugin.getRegistry().getAutomatedCraftingChamberRecipes().get(input);
if (output != null && menu.fits(output, getOutputSlots())) {
menu.pushItem(output.clone(), getOutputSlots());
ChargableBlock.addCharge(block, -getEnergyConsumption());
removeCharge(block.getLocation(), getEnergyConsumption());
for (int j = 0; j < 9; j++) {
if (menu.getItemInSlot(getInputSlots()[j]) != null) {

View File

@ -11,7 +11,6 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
/**
@ -45,7 +44,7 @@ public class ChargingBench extends AContainer {
@Override
protected void tick(Block b) {
if (ChargableBlock.getCharge(b) < getEnergyConsumption()) {
if (getCharge(b.getLocation()) < getEnergyConsumption()) {
return;
}
@ -67,7 +66,7 @@ public class ChargingBench extends AContainer {
float charge = getEnergyConsumption() / 2F;
if (((Rechargeable) sfItem).addItemCharge(item, charge)) {
ChargableBlock.addCharge(b, -getEnergyConsumption());
removeCharge(b.getLocation(), getEnergyConsumption());
}
else if (inv.fits(item, getOutputSlots())) {
inv.pushItem(item, getOutputSlots());

View File

@ -9,30 +9,19 @@ import org.bukkit.block.Block;
import org.bukkit.block.data.Ageable;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
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.interfaces.InventoryBlock;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
public abstract class CropGrowthAccelerator extends SlimefunItem implements InventoryBlock, EnergyNetComponent {
public abstract class CropGrowthAccelerator extends AbstractGrowthAccelerator {
private final int[] border = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 };
private final Set<Material> crops = EnumSet.noneOf(Material.class);
// We wanna strip the Slimefun Item id here
@ -51,24 +40,6 @@ public abstract class CropGrowthAccelerator extends SlimefunItem implements Inve
if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
crops.add(Material.SWEET_BERRY_BUSH);
}
createPreset(this, this::constructMenu);
registerBlockHandler(getID(), (p, b, tool, reason) -> {
BlockMenu inv = BlockStorage.getInventory(b);
if (inv != null) {
inv.dropItems(b.getLocation(), getInputSlots());
}
return true;
});
}
private void constructMenu(BlockMenuPreset preset) {
for (int i : border) {
preset.addItem(i, new CustomItem(new ItemStack(Material.CYAN_STAINED_GLASS_PANE), " "), ChestMenuUtils.getEmptyClickHandler());
}
}
public abstract int getEnergyConsumption();
@ -77,46 +48,16 @@ public abstract class CropGrowthAccelerator extends SlimefunItem implements Inve
public abstract int getSpeed();
@Override
public int[] getInputSlots() {
return new int[] { 10, 11, 12, 13, 14, 15, 16 };
}
@Override
public int[] getOutputSlots() {
return new int[0];
}
@Override
public EnergyNetComponentType getEnergyComponentType() {
return EnergyNetComponentType.CONSUMER;
}
@Override
public int getCapacity() {
return 1024;
}
@Override
public void preRegister() {
addItemHandler(new BlockTicker() {
@Override
public void tick(Block b, SlimefunItem sf, Config data) {
CropGrowthAccelerator.this.tick(b);
}
@Override
public boolean isSynchronized() {
return true;
}
});
}
protected void tick(Block b) {
BlockMenu inv = BlockStorage.getInventory(b);
if (ChargableBlock.getCharge(b) >= getEnergyConsumption()) {
if (getCharge(b.getLocation()) >= getEnergyConsumption()) {
for (int x = -getRadius(); x <= getRadius(); x++) {
for (int z = -getRadius(); z <= getRadius(); z++) {
Block block = b.getRelative(x, 0, z);
@ -134,8 +75,8 @@ public abstract class CropGrowthAccelerator extends SlimefunItem implements Inve
if (ageable.getAge() < ageable.getMaximumAge()) {
for (int slot : getInputSlots()) {
if (SlimefunUtils.isItemSimilar(inv.getItemInSlot(slot), organicFertilizer, false)) {
ChargableBlock.addCharge(machine, -getEnergyConsumption());
if (SlimefunUtils.isItemSimilar(inv.getItemInSlot(slot), organicFertilizer, false, false)) {
removeCharge(machine.getLocation(), getEnergyConsumption());
inv.consumeItem(slot);
ageable.setAge(ageable.getAge() + 1);

View File

@ -1,22 +1,17 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.OreWasher;
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.SlimefunItem.abstractItems.AContainer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
public abstract class ElectricDustWasher extends AContainer {
@ -42,83 +37,40 @@ public abstract class ElectricDustWasher extends AContainer {
return new ItemStack(Material.GOLDEN_SHOVEL);
}
public abstract int getSpeed();
@Override
protected void tick(Block b) {
BlockMenu menu = BlockStorage.getInventory(b);
if (isProcessing(b)) {
int timeleft = progress.get(b);
if (timeleft > 0 && getSpeed() < 10) {
ChestMenuUtils.updateProgressbar(menu, 22, timeleft, processing.get(b).getTicks(), getProgressBar());
if (ChargableBlock.getCharge(b) < getEnergyConsumption()) {
return;
protected MachineRecipe findNextRecipe(BlockMenu menu) {
for (int slot : getInputSlots()) {
if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), SlimefunItems.SIFTED_ORE, true, false)) {
if (!legacyMode && !hasFreeSlot(menu)) {
return null;
}
ChargableBlock.addCharge(b, -getEnergyConsumption());
progress.put(b, timeleft - 1);
}
else {
if (ChargableBlock.getCharge(b) < getEnergyConsumption()) {
return;
ItemStack dust = oreWasher.getRandomDust();
MachineRecipe recipe = new MachineRecipe(4 / getSpeed(), new ItemStack[0], new ItemStack[] { dust });
if (!legacyMode || menu.fits(recipe.getOutput()[0], getOutputSlots())) {
menu.consumeItem(slot);
return recipe;
}
ChargableBlock.addCharge(b, -getEnergyConsumption());
menu.replaceExistingItem(22, new CustomItem(new ItemStack(Material.BLACK_STAINED_GLASS_PANE), " "));
menu.pushItem(processing.get(b).getOutput()[0].clone(), getOutputSlots());
progress.remove(b);
processing.remove(b);
}
}
else {
for (int slot : getInputSlots()) {
if (process(b, menu, slot)) {
break;
else if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), SlimefunItems.PULVERIZED_ORE, true)) {
MachineRecipe recipe = new MachineRecipe(4 / getSpeed(), new ItemStack[0], new ItemStack[] { SlimefunItems.PURE_ORE_CLUSTER });
if (menu.fits(recipe.getOutput()[0], getOutputSlots())) {
menu.consumeItem(slot);
return recipe;
}
}
}
}
private boolean process(Block b, BlockMenu menu, int slot) {
if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), SlimefunItems.SIFTED_ORE, true)) {
if (!legacyMode && !hasFreeSlot(menu)) {
return true;
}
ItemStack adding = oreWasher.getRandomDust();
MachineRecipe r = new MachineRecipe(4 / getSpeed(), new ItemStack[0], new ItemStack[] { adding });
if (!legacyMode || menu.fits(r.getOutput()[0], getOutputSlots())) {
menu.consumeItem(slot);
processing.put(b, r);
progress.put(b, r.getTicks());
}
return true;
}
else if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), SlimefunItems.PULVERIZED_ORE, true)) {
MachineRecipe r = new MachineRecipe(4 / getSpeed(), new ItemStack[0], new ItemStack[] { SlimefunItems.PURE_ORE_CLUSTER });
if (menu.fits(r.getOutput()[0], getOutputSlots())) {
menu.consumeItem(slot);
processing.put(b, r);
progress.put(b, r.getTicks());
}
return true;
}
return false;
return null;
}
private boolean hasFreeSlot(BlockMenu menu) {
for (int slot : getOutputSlots()) {
if (menu.getItemInSlot(slot) == null) {
ItemStack item = menu.getItemInSlot(slot);
if (item == null || item.getType() == Material.AIR) {
return true;
}
}

View File

@ -4,22 +4,17 @@ import java.util.ArrayList;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.items.tools.GoldPan;
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.SlimefunItem.abstractItems.AContainer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
public abstract class ElectricGoldPan extends AContainer implements RecipeDisplayItem {
@ -46,51 +41,35 @@ public abstract class ElectricGoldPan extends AContainer implements RecipeDispla
return new ItemStack(Material.DIAMOND_SHOVEL);
}
public abstract int getSpeed();
@Override
protected void tick(Block b) {
BlockMenu menu = BlockStorage.getInventory(b);
protected MachineRecipe findNextRecipe(BlockMenu menu) {
if (!hasFreeSlot(menu)) {
return null;
}
if (isProcessing(b)) {
int timeleft = progress.get(b);
for (int slot : getInputSlots()) {
if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), new ItemStack(Material.GRAVEL), true, false)) {
ItemStack output = goldPan.getRandomOutput();
MachineRecipe recipe = new MachineRecipe(3 / getSpeed(), new ItemStack[0], new ItemStack[] { output });
if (timeleft > 0 && getSpeed() < 10) {
ChestMenuUtils.updateProgressbar(menu, 22, timeleft, processing.get(b).getTicks(), getProgressBar());
if (ChargableBlock.getCharge(b) < getEnergyConsumption()) {
return;
if (output.getType() != Material.AIR && menu.fits(output, getOutputSlots())) {
menu.consumeItem(slot);
return recipe;
}
ChargableBlock.addCharge(b, -getEnergyConsumption());
progress.put(b, timeleft - 1);
}
else {
if (ChargableBlock.getCharge(b) < getEnergyConsumption()) {
return;
else if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), new ItemStack(Material.SOUL_SAND), true, false)) {
ItemStack output = netherGoldPan.getRandomOutput();
MachineRecipe recipe = new MachineRecipe(4 / getSpeed(), new ItemStack[0], new ItemStack[] { output });
if (output.getType() != Material.AIR && menu.fits(output, getOutputSlots())) {
menu.consumeItem(slot);
return recipe;
}
ChargableBlock.addCharge(b, -getEnergyConsumption());
menu.replaceExistingItem(22, new CustomItem(new ItemStack(Material.BLACK_STAINED_GLASS_PANE), " "));
ItemStack output = processing.get(b).getOutput()[0];
if (output.getType() != Material.AIR) {
menu.pushItem(output.clone(), getOutputSlots());
}
progress.remove(b);
processing.remove(b);
}
}
else {
for (int slot : getInputSlots()) {
if (hasFreeSlot(menu) && process(b, menu, slot)) {
break;
}
}
}
return null;
}
private boolean hasFreeSlot(BlockMenu menu) {
@ -103,37 +82,6 @@ public abstract class ElectricGoldPan extends AContainer implements RecipeDispla
return false;
}
private boolean process(Block b, BlockMenu menu, int slot) {
if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), new ItemStack(Material.GRAVEL), true)) {
ItemStack output = goldPan.getRandomOutput();
MachineRecipe r = new MachineRecipe(3 / getSpeed(), new ItemStack[0], new ItemStack[] { output });
if (menu.fits(output, getOutputSlots())) {
menu.consumeItem(slot);
processing.put(b, r);
progress.put(b, r.getTicks());
}
return true;
}
else if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), new ItemStack(Material.SOUL_SAND), true)) {
ItemStack output = netherGoldPan.getRandomOutput();
MachineRecipe r = new MachineRecipe(4 / getSpeed(), new ItemStack[0], new ItemStack[] { output });
if (menu.fits(output, getOutputSlots())) {
menu.consumeItem(slot);
processing.put(b, r);
progress.put(b, r.getTicks());
}
return true;
}
return false;
}
@Override
public String getMachineIdentifier() {
return "ELECTRIC_GOLD_PAN";

View File

@ -1,7 +1,6 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines;
import java.util.List;
import java.util.Optional;
import org.bukkit.Material;
import org.bukkit.World;
@ -30,7 +29,6 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
@ -70,14 +68,14 @@ public class FluidPump extends SimpleSlimefunItem<BlockTicker> implements Invent
private void constructMenu(BlockMenuPreset preset) {
for (int i : border) {
preset.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "), ChestMenuUtils.getEmptyClickHandler());
preset.addItem(i, new CustomItem(Material.GRAY_STAINED_GLASS_PANE, " "), ChestMenuUtils.getEmptyClickHandler());
}
for (int i : inputBorder) {
preset.addItem(i, new CustomItem(new ItemStack(Material.CYAN_STAINED_GLASS_PANE), " "), ChestMenuUtils.getEmptyClickHandler());
preset.addItem(i, new CustomItem(Material.CYAN_STAINED_GLASS_PANE, " "), ChestMenuUtils.getEmptyClickHandler());
}
for (int i : outputBorder) {
preset.addItem(i, new CustomItem(new ItemStack(Material.ORANGE_STAINED_GLASS_PANE), " "), ChestMenuUtils.getEmptyClickHandler());
preset.addItem(i, new CustomItem(Material.ORANGE_STAINED_GLASS_PANE, " "), ChestMenuUtils.getEmptyClickHandler());
}
for (int i : getOutputSlots()) {
@ -118,21 +116,26 @@ public class FluidPump extends SimpleSlimefunItem<BlockTicker> implements Invent
protected void tick(Block b) {
Block fluid = b.getRelative(BlockFace.DOWN);
Optional<ItemStack> bucket = getFilledBucket(fluid);
if (bucket.isPresent() && ChargableBlock.getCharge(b) >= ENERGY_CONSUMPTION) {
if (fluid.isLiquid() && getCharge(b.getLocation()) >= ENERGY_CONSUMPTION) {
BlockMenu menu = BlockStorage.getInventory(b);
for (int slot : getInputSlots()) {
if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), new ItemStack(Material.BUCKET), true)) {
if (!menu.fits(bucket.get(), getOutputSlots())) {
if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), new ItemStack(Material.BUCKET), true, false)) {
ItemStack bucket = getFilledBucket(fluid);
if (!menu.fits(bucket, getOutputSlots())) {
return;
}
ChargableBlock.addCharge(b, -ENERGY_CONSUMPTION);
menu.consumeItem(slot);
menu.pushItem(bucket.get().clone(), getOutputSlots());
consumeFluid(fluid);
Block nextFluid = findNextFluid(fluid);
if (nextFluid != null) {
removeCharge(b.getLocation(), ENERGY_CONSUMPTION);
menu.consumeItem(slot);
menu.pushItem(bucket, getOutputSlots());
nextFluid.setType(Material.AIR);
}
return;
}
@ -140,48 +143,61 @@ public class FluidPump extends SimpleSlimefunItem<BlockTicker> implements Invent
}
}
private void consumeFluid(Block fluid) {
if (fluid.isLiquid()) {
if (fluid.getType() == Material.WATER || fluid.getType() == Material.BUBBLE_COLUMN) {
// With water we can be sure to find an infinite source whenever we go
// further than 2 blocks, so we can just remove the water here and save
// outselves all of that computing...
fluid.setType(Material.AIR);
}
else {
List<Block> list = Vein.find(fluid, RANGE, block -> isLiquid(block) && block.getType() == fluid.getType());
list.get(list.size() - 1).setType(Material.AIR);
private Block findNextFluid(Block fluid) {
if (fluid.getType() == Material.WATER || fluid.getType() == Material.BUBBLE_COLUMN) {
// With water we can be sure to find an infinite source whenever we go
// further than a block, so we can just remove the water here and save
// ourselves all of that computing...
if (isSource(fluid)) {
return fluid;
}
}
else if (fluid.getType() == Material.LAVA) {
List<Block> list = Vein.find(fluid, RANGE, block -> block.getType() == fluid.getType());
for (int i = list.size() - 1; i >= 0; i--) {
Block block = list.get(i);
if (isSource(block)) {
return block;
}
}
}
return null;
}
private Optional<ItemStack> getFilledBucket(Block fluid) {
private ItemStack getFilledBucket(Block fluid) {
if (fluid.getType() == Material.LAVA) {
return Optional.of(new ItemStack(Material.LAVA_BUCKET));
return new ItemStack(Material.LAVA_BUCKET);
}
else if (fluid.getType() == Material.WATER || fluid.getType() == Material.BUBBLE_COLUMN) {
return Optional.of(new ItemStack(Material.WATER_BUCKET));
return new ItemStack(Material.WATER_BUCKET);
}
else {
return Optional.empty();
// Fallback for any new liquids
return new ItemStack(Material.BUCKET);
}
}
private boolean isLiquid(Block block) {
/**
* This method checks if the given {@link Block} is a liquid source {@link Block}.
*
* @param block
* The {@link Block} in question
*
* @return Whether that {@link Block} is a liquid and a source {@link Block}.
*/
private boolean isSource(Block block) {
if (block.isLiquid()) {
BlockData data = block.getBlockData();
if (data instanceof Levelled) {
// Check if this is a full block.
return ((Levelled) data).getLevel() == 0;
}
else {
return false;
Levelled levelled = (Levelled) data;
return levelled.getLevel() == 0;
}
}
else {
return false;
}
return false;
}
@Override
@ -199,5 +215,4 @@ public class FluidPump extends SimpleSlimefunItem<BlockTicker> implements Invent
}
};
}
}

View File

@ -3,9 +3,7 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machine
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bukkit.Material;
import org.bukkit.block.Block;
@ -16,19 +14,11 @@ import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
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.AContainer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
@ -57,7 +47,9 @@ public abstract class HeatedPressureChamber extends AContainer {
@Override
public int[] getSlotsAccessedByItemTransport(DirtyChestMenu menu, ItemTransportFlow flow, ItemStack item) {
if (flow == ItemTransportFlow.WITHDRAW) return getOutputSlots();
if (flow == ItemTransportFlow.WITHDRAW) {
return getOutputSlots();
}
List<Integer> slots = new ArrayList<>();
@ -107,98 +99,6 @@ public abstract class HeatedPressureChamber extends AContainer {
return new ItemStack(Material.FLINT_AND_STEEL);
}
@Override
public int[] getInputSlots() {
return new int[] { 19, 20 };
}
@Override
public int[] getOutputSlots() {
return new int[] { 24, 25 };
}
@Override
public void preRegister() {
addItemHandler(new BlockTicker() {
@Override
public void tick(Block b, SlimefunItem sf, Config data) {
HeatedPressureChamber.this.tick(b);
}
@Override
public boolean isSynchronized() {
return false;
}
});
}
@Override
protected void tick(Block b) {
BlockMenu menu = BlockStorage.getInventory(b);
if (isProcessing(b)) {
int timeleft = progress.get(b);
if (timeleft > 0) {
ChestMenuUtils.updateProgressbar(menu, 22, timeleft, processing.get(b).getTicks(), getProgressBar());
if (ChargableBlock.getCharge(b) < getEnergyConsumption()) {
return;
}
ChargableBlock.addCharge(b, -getEnergyConsumption());
progress.put(b, timeleft - 1);
}
else {
menu.replaceExistingItem(22, new CustomItem(new ItemStack(Material.BLACK_STAINED_GLASS_PANE), " "));
menu.pushItem(processing.get(b).getOutput()[0], getOutputSlots());
progress.remove(b);
processing.remove(b);
}
}
else {
Map<Integer, Integer> found = new HashMap<>();
MachineRecipe recipe = findRecipe(menu, found);
if (recipe != null) {
if (!menu.fits(recipe.getOutput()[0], getOutputSlots())) {
return;
}
for (Map.Entry<Integer, Integer> entry : found.entrySet()) {
menu.consumeItem(entry.getKey(), entry.getValue());
}
processing.put(b, recipe);
progress.put(b, recipe.getTicks());
}
}
}
private MachineRecipe findRecipe(BlockMenu menu, Map<Integer, Integer> found) {
for (MachineRecipe recipe : recipes) {
for (ItemStack input : recipe.getInput()) {
for (int slot : getInputSlots()) {
if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), input, true)) {
found.put(slot, input.getAmount());
break;
}
}
}
if (found.size() == recipe.getInput().length) {
return recipe;
}
else {
found.clear();
}
}
return null;
}
@Override
public String getMachineIdentifier() {
return "HEATED_PRESSURE_CHAMBER";

View File

@ -1,30 +1,19 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.Tag;
import org.bukkit.block.Block;
import org.bukkit.block.data.type.Sapling;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
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.interfaces.InventoryBlock;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
/**
* The {@link TreeGrowthAccelerator} is an electrical machine that works similar to
@ -36,9 +25,7 @@ import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
* @see AnimalGrowthAccelerator
*
*/
public class TreeGrowthAccelerator extends SlimefunItem implements InventoryBlock, EnergyNetComponent {
private static final int[] border = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 };
public class TreeGrowthAccelerator extends AbstractGrowthAccelerator {
private static final int ENERGY_CONSUMPTION = 24;
private static final int RADIUS = 9;
@ -48,39 +35,6 @@ public class TreeGrowthAccelerator extends SlimefunItem implements InventoryBloc
public TreeGrowthAccelerator(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
createPreset(this, this::constructMenu);
registerBlockHandler(getID(), (p, b, tool, reason) -> {
BlockMenu inv = BlockStorage.getInventory(b);
if (inv != null) {
inv.dropItems(b.getLocation(), getInputSlots());
}
return true;
});
}
protected void constructMenu(BlockMenuPreset preset) {
for (int i : border) {
preset.addItem(i, new CustomItem(new ItemStack(Material.CYAN_STAINED_GLASS_PANE), " "), ChestMenuUtils.getEmptyClickHandler());
}
}
@Override
public int[] getInputSlots() {
return new int[] { 10, 11, 12, 13, 14, 15, 16 };
}
@Override
public int[] getOutputSlots() {
return new int[0];
}
@Override
public EnergyNetComponentType getEnergyComponentType() {
return EnergyNetComponentType.CONSUMER;
}
@Override
@ -89,25 +43,10 @@ public class TreeGrowthAccelerator extends SlimefunItem implements InventoryBloc
}
@Override
public void preRegister() {
addItemHandler(new BlockTicker() {
@Override
public void tick(Block b, SlimefunItem sf, Config data) {
TreeGrowthAccelerator.this.tick(b);
}
@Override
public boolean isSynchronized() {
return true;
}
});
}
protected void tick(Block b) {
BlockMenu inv = BlockStorage.getInventory(b);
if (ChargableBlock.getCharge(b) >= ENERGY_CONSUMPTION) {
if (getCharge(b.getLocation()) >= ENERGY_CONSUMPTION) {
for (int x = -RADIUS; x <= RADIUS; x++) {
for (int z = -RADIUS; z <= RADIUS; z++) {
Block block = b.getRelative(x, 0, z);
@ -115,7 +54,7 @@ public class TreeGrowthAccelerator extends SlimefunItem implements InventoryBloc
if (Tag.SAPLINGS.isTagged(block.getType())) {
Sapling sapling = (Sapling) block.getBlockData();
if (sapling.getStage() < sapling.getMaximumStage() && grow(b, block, inv, sapling)) {
if (sapling.getStage() < sapling.getMaximumStage() && growSapling(b, block, inv, sapling)) {
return;
}
}
@ -124,10 +63,10 @@ public class TreeGrowthAccelerator extends SlimefunItem implements InventoryBloc
}
}
private boolean grow(Block machine, Block block, BlockMenu inv, Sapling sapling) {
private boolean growSapling(Block machine, Block block, BlockMenu inv, Sapling sapling) {
for (int slot : getInputSlots()) {
if (SlimefunUtils.isItemSimilar(inv.getItemInSlot(slot), organicFertilizer, false)) {
ChargableBlock.addCharge(machine, -ENERGY_CONSUMPTION);
if (SlimefunUtils.isItemSimilar(inv.getItemInSlot(slot), organicFertilizer, false, false)) {
removeCharge(machine.getLocation(), ENERGY_CONSUMPTION);
sapling.setStage(sapling.getStage() + 1);
block.setBlockData(sapling, false);

View File

@ -22,7 +22,6 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
@ -109,13 +108,13 @@ public class XPCollector extends SlimefunItem implements InventoryBlock, EnergyN
while (iterator.hasNext() && experiencePoints == 0) {
Entity entity = iterator.next();
if (ChargableBlock.getCharge(b) < ENERGY_CONSUMPTION) {
if (getCharge(b.getLocation()) < ENERGY_CONSUMPTION) {
return;
}
experiencePoints = getStoredExperience(b) + ((ExperienceOrb) entity).getExperience();
ChargableBlock.addCharge(b, -ENERGY_CONSUMPTION);
removeCharge(b.getLocation(), ENERGY_CONSUMPTION);
entity.remove();
int withdrawn = 0;

View File

@ -27,7 +27,6 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
@ -143,12 +142,11 @@ public abstract class GEOMiner extends AContainer implements RecipeDisplayItem {
if (timeleft > 0) {
ChestMenuUtils.updateProgressbar(inv, 4, timeleft, processing.get(b).getTicks(), getProgressBar());
if (ChargableBlock.getCharge(b) < getEnergyConsumption()) {
if (getCharge(b.getLocation()) < getEnergyConsumption()) {
return;
}
ChargableBlock.addCharge(b, -getEnergyConsumption());
removeCharge(b.getLocation(), getEnergyConsumption());
progress.put(b, timeleft - 1);
}
else {

View File

@ -10,21 +10,17 @@ import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
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.SlimefunItem.abstractItems.AContainer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
@ -81,62 +77,39 @@ public abstract class OilPump extends AContainer implements RecipeDisplayItem {
return "OIL_PUMP";
}
@Override
public String getInventoryTitle() {
return "&4Oil Pump";
}
@Override
public ItemStack getProgressBar() {
return new ItemStack(Material.DIAMOND_SHOVEL);
}
@Override
protected void tick(Block b) {
BlockMenu inv = BlockStorage.getInventory(b);
protected MachineRecipe findNextRecipe(BlockMenu inv) {
if (inv.fits(SlimefunItems.OIL_BUCKET, getOutputSlots())) {
Block b = inv.getBlock();
if (isProcessing(b)) {
int timeleft = progress.get(b);
if (timeleft > 0) {
ChestMenuUtils.updateProgressbar(inv, 22, timeleft, processing.get(b).getTicks(), getProgressBar());
if (ChargableBlock.getCharge(b) < getEnergyConsumption()) {
return;
}
ChargableBlock.addCharge(b, -getEnergyConsumption());
progress.put(b, timeleft - 1);
}
else {
inv.replaceExistingItem(22, new CustomItem(Material.BLACK_STAINED_GLASS_PANE, " "));
inv.pushItem(SlimefunItems.OIL_BUCKET, getOutputSlots());
progress.remove(b);
processing.remove(b);
}
}
else if (inv.fits(SlimefunItems.OIL_BUCKET, getOutputSlots())) {
for (int slot : getInputSlots()) {
if (SlimefunUtils.isItemSimilar(inv.getItemInSlot(slot), new ItemStack(Material.BUCKET), true, false)) {
OptionalInt supplies = SlimefunPlugin.getGPSNetwork().getResourceManager().getSupplies(oil, b.getWorld(), b.getX() >> 4, b.getZ() >> 4);
if (supplies.isPresent() && supplies.getAsInt() > 0) {
MachineRecipe r = new MachineRecipe(26, new ItemStack[0], new ItemStack[] { SlimefunItems.OIL_BUCKET });
MachineRecipe recipe = new MachineRecipe(26, new ItemStack[0], new ItemStack[] { SlimefunItems.OIL_BUCKET });
inv.consumeItem(slot);
processing.put(b, r);
progress.put(b, r.getTicks());
SlimefunPlugin.getGPSNetwork().getResourceManager().setSupplies(oil, b.getWorld(), b.getX() >> 4, b.getZ() >> 4, supplies.getAsInt() - 1);
return recipe;
}
else {
// Move the empty bucket to the output slot to prevent this
// from immediately starting all over again (to prevent lag)
ItemStack item = inv.getItemInSlot(slot).clone();
inv.replaceExistingItem(slot, null);
inv.pushItem(item, getOutputSlots());
return null;
}
break;
}
}
}
return null;
}
}

View File

@ -18,12 +18,14 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
public abstract class GPSTransmitter extends SimpleSlimefunItem<BlockTicker> implements EnergyNetComponent {
public GPSTransmitter(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
private final int capacity;
public GPSTransmitter(Category category, int tier, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
this.capacity = 4 << (2 * tier);
addItemHandler(onPlace());
registerBlockHandler(getID(), (p, b, stack, reason) -> {
@ -33,6 +35,11 @@ public abstract class GPSTransmitter extends SimpleSlimefunItem<BlockTicker> imp
});
}
@Override
public int getCapacity() {
return capacity;
}
private BlockPlaceHandler onPlace() {
return new BlockPlaceHandler(false) {
@ -53,12 +60,12 @@ public abstract class GPSTransmitter extends SimpleSlimefunItem<BlockTicker> imp
@Override
public void tick(Block b, SlimefunItem item, Config data) {
int charge = ChargableBlock.getCharge(b);
int charge = getCharge(b.getLocation());
UUID owner = UUID.fromString(BlockStorage.getLocationInfo(b.getLocation(), "owner"));
if (charge >= getEnergyConsumption()) {
SlimefunPlugin.getGPSNetwork().updateTransmitter(b.getLocation(), owner, true);
ChargableBlock.setCharge(b.getLocation(), charge - getEnergyConsumption());
removeCharge(b.getLocation(), getEnergyConsumption());
}
else {
SlimefunPlugin.getGPSNetwork().updateTransmitter(b.getLocation(), owner, false);

View File

@ -31,7 +31,10 @@ public class WindStaff extends SimpleSlimefunItem<ItemUseHandler> {
if (p.getInventory().getItemInMainHand().getType() != Material.SHEARS && p.getGameMode() != GameMode.CREATIVE) {
FoodLevelChangeEvent event = new FoodLevelChangeEvent(p, p.getFoodLevel() - 2);
Bukkit.getPluginManager().callEvent(event);
p.setFoodLevel(event.getFoodLevel());
if (!event.isCancelled()) {
p.setFoodLevel(event.getFoodLevel());
}
}
p.setVelocity(p.getEyeLocation().getDirection().multiply(4));

View File

@ -0,0 +1,50 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.medical;
import javax.annotation.Nonnull;
import org.bukkit.attribute.Attribute;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemHandler;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public abstract class MedicalSupply<T extends ItemHandler> extends SimpleSlimefunItem<T> {
private final int healAmount;
public MedicalSupply(Category category, int healAmount, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
this.healAmount = healAmount;
}
/**
* This method clears any negative {@link PotionEffect} from the given {@link Player}.
*
* @param p
* The {@link Player}
*/
public void clearNegativeEffects(@Nonnull Player p) {
if (p.hasPotionEffect(PotionEffectType.POISON)) p.removePotionEffect(PotionEffectType.POISON);
if (p.hasPotionEffect(PotionEffectType.WITHER)) p.removePotionEffect(PotionEffectType.WITHER);
if (p.hasPotionEffect(PotionEffectType.SLOW)) p.removePotionEffect(PotionEffectType.SLOW);
if (p.hasPotionEffect(PotionEffectType.SLOW_DIGGING)) p.removePotionEffect(PotionEffectType.SLOW_DIGGING);
if (p.hasPotionEffect(PotionEffectType.WEAKNESS)) p.removePotionEffect(PotionEffectType.WEAKNESS);
if (p.hasPotionEffect(PotionEffectType.CONFUSION)) p.removePotionEffect(PotionEffectType.CONFUSION);
if (p.hasPotionEffect(PotionEffectType.BLINDNESS)) p.removePotionEffect(PotionEffectType.BLINDNESS);
if (p.hasPotionEffect(PotionEffectType.BAD_OMEN)) p.removePotionEffect(PotionEffectType.BLINDNESS);
}
public void heal(@Nonnull Player p) {
double health = p.getHealth() + healAmount;
double maxHealth = p.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
p.setHealth(Math.min(health, maxHealth));
}
}

View File

@ -1,39 +1,24 @@
package io.github.thebusybiscuit.slimefun4.implementation.items.medical;
import org.bukkit.attribute.Attribute;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffectType;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemConsumptionHandler;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class Medicine extends SimpleSlimefunItem<ItemConsumptionHandler> {
private static final double HEALING_AMOUNT = 8.0;
public class Medicine extends MedicalSupply<ItemConsumptionHandler> {
public Medicine(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
super(category, 8, item, recipeType, recipe);
}
@Override
public ItemConsumptionHandler getItemHandler() {
return (e, p, item) -> {
if (p.hasPotionEffect(PotionEffectType.POISON)) p.removePotionEffect(PotionEffectType.POISON);
if (p.hasPotionEffect(PotionEffectType.WITHER)) p.removePotionEffect(PotionEffectType.WITHER);
if (p.hasPotionEffect(PotionEffectType.SLOW)) p.removePotionEffect(PotionEffectType.SLOW);
if (p.hasPotionEffect(PotionEffectType.SLOW_DIGGING)) p.removePotionEffect(PotionEffectType.SLOW_DIGGING);
if (p.hasPotionEffect(PotionEffectType.WEAKNESS)) p.removePotionEffect(PotionEffectType.WEAKNESS);
if (p.hasPotionEffect(PotionEffectType.CONFUSION)) p.removePotionEffect(PotionEffectType.CONFUSION);
if (p.hasPotionEffect(PotionEffectType.BLINDNESS)) p.removePotionEffect(PotionEffectType.BLINDNESS);
double health = p.getHealth() + HEALING_AMOUNT;
double maxHealth = p.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
p.setHealth(Math.min(health, maxHealth));
p.setFireTicks(0);
clearNegativeEffects(p);
heal(p);
};
}

View File

@ -2,52 +2,35 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.medical;
import org.bukkit.GameMode;
import org.bukkit.Sound;
import org.bukkit.attribute.Attribute;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffectType;
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler;
import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
public class Vitamins extends SimpleSlimefunItem<ItemUseHandler> {
private static final double HEALING_AMOUNT = 8.0;
public class Vitamins extends MedicalSupply<ItemUseHandler> {
public Vitamins(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
super(category, item, recipeType, recipe);
super(category, 8, item, recipeType, recipe);
}
@Override
public ItemUseHandler getItemHandler() {
return e -> {
Player p = e.getPlayer();
p.getWorld().playSound(p.getLocation(), Sound.ENTITY_GENERIC_EAT, 1, 1);
if (p.getGameMode() != GameMode.CREATIVE) {
ItemUtils.consumeItem(e.getItem(), false);
}
p.getWorld().playSound(p.getLocation(), Sound.ENTITY_GENERIC_EAT, 1, 1);
if (p.hasPotionEffect(PotionEffectType.POISON)) p.removePotionEffect(PotionEffectType.POISON);
if (p.hasPotionEffect(PotionEffectType.WITHER)) p.removePotionEffect(PotionEffectType.WITHER);
if (p.hasPotionEffect(PotionEffectType.SLOW)) p.removePotionEffect(PotionEffectType.SLOW);
if (p.hasPotionEffect(PotionEffectType.SLOW_DIGGING)) p.removePotionEffect(PotionEffectType.SLOW_DIGGING);
if (p.hasPotionEffect(PotionEffectType.WEAKNESS)) p.removePotionEffect(PotionEffectType.WEAKNESS);
if (p.hasPotionEffect(PotionEffectType.CONFUSION)) p.removePotionEffect(PotionEffectType.CONFUSION);
if (p.hasPotionEffect(PotionEffectType.BLINDNESS)) p.removePotionEffect(PotionEffectType.BLINDNESS);
p.setFireTicks(0);
double health = p.getHealth() + HEALING_AMOUNT;
double maxHealth = p.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue();
p.setHealth(Math.min(health, maxHealth));
e.cancel();
p.setFireTicks(0);
clearNegativeEffects(p);
heal(p);
};
}

View File

@ -37,7 +37,6 @@ public class EnhancedCraftingTable extends BackpackCrafter {
if (state instanceof Dispenser) {
Dispenser disp = (Dispenser) state;
Inventory inv = disp.getInventory();
List<ItemStack[]> inputs = RecipeType.getRecipeInputList(this);
for (int i = 0; i < inputs.size(); i++) {
@ -51,6 +50,7 @@ public class EnhancedCraftingTable extends BackpackCrafter {
return;
}
}
SlimefunPlugin.getLocalization().sendMessage(p, "machines.pattern-not-found", true);
}
}

View File

@ -3,6 +3,8 @@ package io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.block.Block;
@ -30,7 +32,7 @@ public class GrindStone extends MultiBlockMachine {
}
@Override
protected void registerDefaultRecipes(List<ItemStack> recipes) {
protected void registerDefaultRecipes(@Nonnull List<ItemStack> recipes) {
recipes.add(new ItemStack(Material.BLAZE_ROD));
recipes.add(new ItemStack(Material.BLAZE_POWDER, 4));
@ -106,6 +108,7 @@ public class GrindStone extends MultiBlockMachine {
}
}
}
SlimefunPlugin.getLocalization().sendMessage(p, "machines.unknown-material", true);
}
}

View File

@ -6,6 +6,8 @@ import java.util.List;
import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.Nonnull;
import org.bukkit.Effect;
import org.bukkit.Material;
import org.bukkit.Sound;
@ -40,7 +42,7 @@ public class Smeltery extends AbstractSmeltery {
}
@Override
protected void registerDefaultRecipes(List<ItemStack> recipes) {
protected void registerDefaultRecipes(@Nonnull List<ItemStack> recipes) {
recipes.add(SlimefunItems.IRON_DUST);
recipes.add(new ItemStack(Material.IRON_INGOT));
}
@ -50,7 +52,7 @@ public class Smeltery extends AbstractSmeltery {
List<ItemStack> items = new ArrayList<>();
for (int i = 0; i < recipes.size() - 1; i += 2) {
if (Arrays.stream(recipes.get(i)).skip(1).anyMatch(Objects::nonNull)) {
if (recipes.get(i) == null || Arrays.stream(recipes.get(i)).skip(1).anyMatch(Objects::nonNull)) {
continue;
}
@ -102,7 +104,7 @@ public class Smeltery extends AbstractSmeltery {
}
}
private Inventory findIgnitionChamber(Block b) {
private Inventory findIgnitionChamber(@Nonnull Block b) {
for (BlockFace face : faces) {
if (b.getRelative(face).getType() == Material.DROPPER && BlockStorage.check(b.getRelative(face), "IGNITION_CHAMBER")) {
BlockState state = PaperLib.getBlockState(b.getRelative(face), false).getState();

View File

@ -116,6 +116,9 @@ class ExplosiveTool extends SimpleSlimefunItem<ToolUseHandler> implements NotPla
else if (MaterialCollections.getAllUnbreakableBlocks().contains(b.getType())) {
return false;
}
else if (!b.getWorld().getWorldBorder().isInside(b.getLocation())) {
return false;
}
else {
return SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.BREAK_BLOCK);
}

View File

@ -5,6 +5,8 @@ import org.bukkit.Sound;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.FoodLevelChangeEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
@ -19,10 +21,11 @@ import io.github.thebusybiscuit.slimefun4.implementation.items.food.Juice;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This {@link Listener} listens for a {@link FoodLevelChangeEvent} and consumes a {@link Juice}
* from any {@link Cooler} that can be found in the {@link Inventory} of the given {@link Player}.
* This {@link Listener} listens for a {@link FoodLevelChangeEvent} or an {@link EntityDamageEvent} for starvation damage
* and consumes a {@link Juice} from any {@link Cooler} that can be found in the {@link Inventory} of the given {@link Player}.
*
* @author TheBusyBiscuit
* @author Linox
*
* @see Cooler
* @see Juice
@ -40,21 +43,36 @@ public class CoolerListener implements Listener {
@EventHandler
public void onHungerLoss(FoodLevelChangeEvent e) {
if (cooler == null || cooler.isDisabled()) {
if (cooler == null || cooler.isDisabled() || !(e.getEntity() instanceof Player)) {
return;
}
Player p = (Player) e.getEntity();
if (e.getFoodLevel() < p.getFoodLevel()) {
for (ItemStack item : p.getInventory().getContents()) {
if (cooler.isItem(item)) {
if (Slimefun.hasUnlocked(p, cooler, true)) {
takeJuiceFromCooler(p, item);
}
else {
return;
}
checkAndConsume(p);
}
}
@EventHandler
public void onHungerDamage(EntityDamageEvent e) {
if (cooler == null || cooler.isDisabled() || !(e.getEntity() instanceof Player)) {
return;
}
if (e.getCause() == DamageCause.STARVATION) {
checkAndConsume((Player) e.getEntity());
}
}
private void checkAndConsume(Player p) {
for (ItemStack item : p.getInventory().getContents()) {
if (cooler.isItem(item)) {
if (Slimefun.hasUnlocked(p, cooler, true)) {
takeJuiceFromCooler(p, item);
}
else {
return;
}
}
}

View File

@ -19,7 +19,6 @@ import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
import io.github.thebusybiscuit.cscorelib2.skull.SkullBlock;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetProvider;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNet;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
@ -27,7 +26,6 @@ import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
/**
* This {@link Listener} is responsible for handling our debugging tool, the debug fish.
@ -144,16 +142,18 @@ public class DebugFishListener implements Listener {
p.sendMessage(ChatColors.color(" &dChunk Timings: &e" + SlimefunPlugin.getProfiler().getTime(b.getChunk())));
}
if (ChargableBlock.isChargable(b)) {
p.sendMessage(ChatColors.color("&dChargeable: " + greenCheckmark));
p.sendMessage(ChatColors.color(" &dEnergy: &e" + ChargableBlock.getCharge(b) + " / " + ChargableBlock.getMaxCharge(b)));
}
else {
p.sendMessage(ChatColors.color("&dChargeable: " + redCross));
}
if (item instanceof EnergyNetComponent) {
p.sendMessage(ChatColors.color(" &dEnergyNet Type: &e" + EnergyNet.getComponent(b.getLocation())));
EnergyNetComponent component = (EnergyNetComponent) item;
p.sendMessage(ChatColors.color("&dEnergyNet Component"));
p.sendMessage(ChatColors.color(" &dType: &e" + component.getEnergyComponentType()));
if (component.isChargeable()) {
p.sendMessage(ChatColors.color(" &dChargeable: " + greenCheckmark));
p.sendMessage(ChatColors.color(" &dEnergy: &e" + component.getCharge(b.getLocation()) + " / " + component.getCapacity()));
}
else {
p.sendMessage(ChatColors.color("&dChargeable: " + redCross));
}
}
p.sendMessage(ChatColors.color("&6" + BlockStorage.getBlockInfoAsJson(b)));

View File

@ -1,46 +1,19 @@
package io.github.thebusybiscuit.slimefun4.implementation.resources;
import org.bukkit.NamespacedKey;
import org.bukkit.World.Environment;
import org.bukkit.block.Biome;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class NetherIceResource implements GEOResource {
class NetherIceResource extends SlimefunResource {
private final NamespacedKey key = new NamespacedKey(SlimefunPlugin.instance(), "nether_ice");
NetherIceResource() {
super("nether_ice", "Nether Ice", SlimefunItems.NETHER_ICE, 6, true);
}
@Override
public int getDefaultSupply(Environment environment, Biome biome) {
return environment == Environment.NETHER ? 32 : 0;
}
@Override
public NamespacedKey getKey() {
return key;
}
@Override
public int getMaxDeviation() {
return 6;
}
@Override
public String getName() {
return "Nether Ice";
}
@Override
public ItemStack getItem() {
return SlimefunItems.NETHER_ICE.clone();
}
@Override
public boolean isObtainableFromGEOMiner() {
return true;
}
}

View File

@ -1,17 +1,15 @@
package io.github.thebusybiscuit.slimefun4.implementation.resources;
import org.bukkit.NamespacedKey;
import org.bukkit.World.Environment;
import org.bukkit.block.Biome;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class OilResource implements GEOResource {
class OilResource extends SlimefunResource {
private final NamespacedKey key = new NamespacedKey(SlimefunPlugin.instance(), "oil");
OilResource() {
super("oil", "Oil", SlimefunItems.OIL_BUCKET, 8, false);
}
@Override
public int getDefaultSupply(Environment environment, Biome biome) {
@ -74,29 +72,4 @@ class OilResource implements GEOResource {
}
}
@Override
public NamespacedKey getKey() {
return key;
}
@Override
public int getMaxDeviation() {
return 8;
}
@Override
public String getName() {
return "Oil";
}
@Override
public ItemStack getItem() {
return SlimefunItems.OIL_BUCKET.clone();
}
@Override
public boolean isObtainableFromGEOMiner() {
return false;
}
}

View File

@ -1,17 +1,15 @@
package io.github.thebusybiscuit.slimefun4.implementation.resources;
import org.bukkit.NamespacedKey;
import org.bukkit.World.Environment;
import org.bukkit.block.Biome;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class SaltResource implements GEOResource {
class SaltResource extends SlimefunResource {
private final NamespacedKey key = new NamespacedKey(SlimefunPlugin.instance(), "salt");
SaltResource() {
super("salt", "Salt", SlimefunItems.SALT, 18, true);
}
@Override
public int getDefaultSupply(Environment environment, Biome biome) {
@ -51,29 +49,4 @@ class SaltResource implements GEOResource {
}
}
@Override
public int getMaxDeviation() {
return 18;
}
@Override
public NamespacedKey getKey() {
return key;
}
@Override
public String getName() {
return "Salt";
}
@Override
public ItemStack getItem() {
return SlimefunItems.SALT.clone();
}
@Override
public boolean isObtainableFromGEOMiner() {
return true;
}
}

View File

@ -0,0 +1,55 @@
package io.github.thebusybiscuit.slimefun4.implementation.resources;
import org.apache.commons.lang.Validate;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
abstract class SlimefunResource implements GEOResource {
private final NamespacedKey key;
private final String defaultName;
private final ItemStack item;
private final int maxDeviation;
private final boolean geoMiner;
SlimefunResource(String key, String defaultName, ItemStack item, int maxDeviation, boolean geoMiner) {
Validate.notNull(key, "NamespacedKey cannot be null!");
Validate.notNull(defaultName, "The default name cannot be null!");
Validate.notNull(item, "item cannot be null!");
this.key = new NamespacedKey(SlimefunPlugin.instance(), key);
this.defaultName = defaultName;
this.item = item;
this.maxDeviation = maxDeviation;
this.geoMiner = geoMiner;
}
@Override
public NamespacedKey getKey() {
return key;
}
@Override
public String getName() {
return defaultName;
}
@Override
public ItemStack getItem() {
return item.clone();
}
@Override
public int getMaxDeviation() {
return maxDeviation;
}
@Override
public boolean isObtainableFromGEOMiner() {
return geoMiner;
}
}

View File

@ -1,17 +1,15 @@
package io.github.thebusybiscuit.slimefun4.implementation.resources;
import org.bukkit.NamespacedKey;
import org.bukkit.World.Environment;
import org.bukkit.block.Biome;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.geo.GEOResource;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
class UraniumResource implements GEOResource {
class UraniumResource extends SlimefunResource {
private final NamespacedKey key = new NamespacedKey(SlimefunPlugin.instance(), "uranium");
UraniumResource() {
super("uranium", "Small Chunks of Uranium", SlimefunItems.SMALL_URANIUM, 2, true);
}
@Override
public int getDefaultSupply(Environment envionment, Biome biome) {
@ -22,29 +20,4 @@ class UraniumResource implements GEOResource {
return 0;
}
@Override
public NamespacedKey getKey() {
return key;
}
@Override
public int getMaxDeviation() {
return 2;
}
@Override
public String getName() {
return "Small Chunks of Uranium";
}
@Override
public ItemStack getItem() {
return SlimefunItems.SMALL_URANIUM.clone();
}
@Override
public boolean isObtainableFromGEOMiner() {
return true;
}
}

View File

@ -2054,14 +2054,9 @@ public final class SlimefunItemSetup {
new ItemStack[] {new ItemStack(Material.REDSTONE), new ItemStack(Material.ANVIL), new ItemStack(Material.REDSTONE), SlimefunItems.CARBONADO, SlimefunItems.AUTO_ENCHANTER, SlimefunItems.CARBONADO, SlimefunItems.WITHER_PROOF_OBSIDIAN, SlimefunItems.WITHER_PROOF_OBSIDIAN, SlimefunItems.WITHER_PROOF_OBSIDIAN})
.register(plugin);
new AutoAnvil(categories.electricity, SlimefunItems.AUTO_ANVIL, RecipeType.ENHANCED_CRAFTING_TABLE,
new AutoAnvil(categories.electricity, 10, SlimefunItems.AUTO_ANVIL, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {null, new ItemStack(Material.ANVIL), null, SlimefunItems.REINFORCED_ALLOY_INGOT, SlimefunItems.ELECTRIC_MOTOR, SlimefunItems.REINFORCED_ALLOY_INGOT, new ItemStack(Material.IRON_BLOCK), new ItemStack(Material.IRON_BLOCK), new ItemStack(Material.IRON_BLOCK)}) {
@Override
public int getRepairFactor() {
return 10;
}
@Override
public int getCapacity() {
return 128;
@ -2074,14 +2069,9 @@ public final class SlimefunItemSetup {
}.register(plugin);
new AutoAnvil(categories.electricity, SlimefunItems.AUTO_ANVIL_2, RecipeType.ENHANCED_CRAFTING_TABLE,
new AutoAnvil(categories.electricity, 25, SlimefunItems.AUTO_ANVIL_2, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {null, SlimefunItems.AUTO_ANVIL, null, SlimefunItems.STEEL_PLATE, SlimefunItems.HEATING_COIL, SlimefunItems.STEEL_PLATE, new ItemStack(Material.IRON_BLOCK), new ItemStack(Material.IRON_BLOCK), new ItemStack(Material.IRON_BLOCK)}) {
@Override
public int getRepairFactor() {
return 4;
}
@Override
public int getCapacity() {
return 256;
@ -2107,7 +2097,7 @@ public final class SlimefunItemSetup {
new ItemStack[] {SlimefunItems.BRASS_INGOT, new ItemStack(Material.ORANGE_STAINED_GLASS), SlimefunItems.BRASS_INGOT, SlimefunItems.POWER_CRYSTAL, SlimefunItems.TIN_DUST, SlimefunItems.POWER_CRYSTAL, SlimefunItems.BRASS_INGOT, new ItemStack(Material.ORANGE_STAINED_GLASS), SlimefunItems.BRASS_INGOT})
.register(plugin);
new GPSTransmitter(categories.gps, SlimefunItems.GPS_TRANSMITTER, RecipeType.ENHANCED_CRAFTING_TABLE,
new GPSTransmitter(categories.gps, 1, SlimefunItems.GPS_TRANSMITTER, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {null, null, SlimefunItems.ELECTRO_MAGNET, SlimefunItems.STEEL_INGOT, SlimefunItems.ADVANCED_CIRCUIT_BOARD, SlimefunItems.STEEL_INGOT, SlimefunItems.STEEL_INGOT, SlimefunItems.ELECTRIC_MOTOR, SlimefunItems.STEEL_INGOT}) {
@Override
@ -2115,11 +2105,6 @@ public final class SlimefunItemSetup {
return y;
}
@Override
public int getCapacity() {
return 16;
}
@Override
public int getEnergyConsumption() {
return 1;
@ -2127,7 +2112,7 @@ public final class SlimefunItemSetup {
}.register(plugin);
new GPSTransmitter(categories.gps, SlimefunItems.GPS_TRANSMITTER_2, RecipeType.ENHANCED_CRAFTING_TABLE,
new GPSTransmitter(categories.gps, 2, SlimefunItems.GPS_TRANSMITTER_2, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {SlimefunItems.GPS_TRANSMITTER, SlimefunItems.BRONZE_INGOT, SlimefunItems.GPS_TRANSMITTER, SlimefunItems.BRONZE_INGOT, SlimefunItems.CARBON, SlimefunItems.BRONZE_INGOT, SlimefunItems.GPS_TRANSMITTER, SlimefunItems.BRONZE_INGOT, SlimefunItems.GPS_TRANSMITTER}) {
@Override
@ -2135,11 +2120,6 @@ public final class SlimefunItemSetup {
return y * 4 + 100;
}
@Override
public int getCapacity() {
return 64;
}
@Override
public int getEnergyConsumption() {
return 3;
@ -2147,7 +2127,7 @@ public final class SlimefunItemSetup {
}.register(plugin);
new GPSTransmitter(categories.gps, SlimefunItems.GPS_TRANSMITTER_3, RecipeType.ENHANCED_CRAFTING_TABLE,
new GPSTransmitter(categories.gps, 3, SlimefunItems.GPS_TRANSMITTER_3, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {SlimefunItems.GPS_TRANSMITTER_2, SlimefunItems.CORINTHIAN_BRONZE_INGOT, SlimefunItems.GPS_TRANSMITTER_2, SlimefunItems.CORINTHIAN_BRONZE_INGOT, SlimefunItems.CARBONADO, SlimefunItems.CORINTHIAN_BRONZE_INGOT, SlimefunItems.GPS_TRANSMITTER_2, SlimefunItems.CORINTHIAN_BRONZE_INGOT, SlimefunItems.GPS_TRANSMITTER_2}) {
@Override
@ -2155,11 +2135,6 @@ public final class SlimefunItemSetup {
return y * 16 + 500;
}
@Override
public int getCapacity() {
return 256;
}
@Override
public int getEnergyConsumption() {
return 11;
@ -2167,7 +2142,7 @@ public final class SlimefunItemSetup {
}.register(plugin);
new GPSTransmitter(categories.gps, SlimefunItems.GPS_TRANSMITTER_4, RecipeType.ENHANCED_CRAFTING_TABLE,
new GPSTransmitter(categories.gps, 4, SlimefunItems.GPS_TRANSMITTER_4, RecipeType.ENHANCED_CRAFTING_TABLE,
new ItemStack[] {SlimefunItems.GPS_TRANSMITTER_3, SlimefunItems.BLISTERING_INGOT_3, SlimefunItems.GPS_TRANSMITTER_3, SlimefunItems.NICKEL_INGOT, SlimefunItems.CARBONADO, SlimefunItems.NICKEL_INGOT, SlimefunItems.GPS_TRANSMITTER_3, SlimefunItems.BLISTERING_INGOT_3, SlimefunItems.GPS_TRANSMITTER_3}) {
@Override
@ -2175,11 +2150,6 @@ public final class SlimefunItemSetup {
return y * 64 + 600;
}
@Override
public int getCapacity() {
return 1024;
}
@Override
public int getEnergyConsumption() {
return 46;

View File

@ -12,6 +12,7 @@ import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.scheduler.BukkitScheduler;
import io.github.thebusybiscuit.cscorelib2.blocks.BlockPosition;
import io.github.thebusybiscuit.slimefun4.api.ErrorReport;
@ -23,79 +24,116 @@ import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* The {@link TickerTask} is responsible for ticking every {@link BlockTicker}, synchronous
* or not.
*
* @author TheBusyBiscuit
*
* @see BlockTicker
*
*/
public class TickerTask implements Runnable {
private final Set<BlockTicker> tickers = new HashSet<>();
// These are "Queues" of blocks that need to be removed or moved
private final Map<Location, Location> movingQueue = new ConcurrentHashMap<>();
private final Map<Location, Boolean> deletionQueue = new ConcurrentHashMap<>();
// This Map tracks how many bugs have occurred in a given Location
// If too many bugs happen, we delete that Location
private final Map<BlockPosition, Integer> bugs = new ConcurrentHashMap<>();
private int tickRate;
private boolean halted = false;
private boolean running = false;
public void abortTick() {
/**
* This method starts the {@link TickerTask} on an asynchronous schedule.
*
* @param plugin
* The instance of our {@link SlimefunPlugin}
*/
public void start(SlimefunPlugin plugin) {
this.tickRate = SlimefunPlugin.getCfg().getInt("URID.custom-ticker-delay");
BukkitScheduler scheduler = plugin.getServer().getScheduler();
scheduler.runTaskTimerAsynchronously(plugin, this, 100L, tickRate);
}
/**
* This method resets this {@link TickerTask} to run again.
*/
public void reset() {
running = false;
}
@Override
public void run() {
if (running) {
return;
}
try {
// If this method is actually still running... DON'T
if (running) {
return;
}
running = true;
SlimefunPlugin.getProfiler().start();
running = true;
SlimefunPlugin.getProfiler().start();
Set<BlockTicker> tickers = new HashSet<>();
Iterator<Map.Entry<Location, Boolean>> removals = deletionQueue.entrySet().iterator();
while (removals.hasNext()) {
Map.Entry<Location, Boolean> entry = removals.next();
BlockStorage.deleteLocationInfoUnsafely(entry.getKey(), entry.getValue());
removals.remove();
}
Iterator<Map.Entry<Location, Boolean>> removals = deletionQueue.entrySet().iterator();
while (removals.hasNext()) {
Map.Entry<Location, Boolean> entry = removals.next();
BlockStorage.deleteLocationInfoUnsafely(entry.getKey(), entry.getValue());
removals.remove();
}
if (!halted) {
for (String chunk : BlockStorage.getTickingChunks()) {
try {
Set<Location> locations = BlockStorage.getTickingLocations(chunk);
String[] components = PatternUtils.SEMICOLON.split(chunk);
World world = Bukkit.getWorld(components[0]);
int x = Integer.parseInt(components[components.length - 2]);
int z = Integer.parseInt(components[components.length - 1]);
if (world != null && world.isChunkLoaded(x, z)) {
for (Location l : locations) {
tick(l);
}
}
if (!halted) {
for (String chunk : BlockStorage.getTickingChunks()) {
tickChunk(tickers, chunk);
}
catch (ArrayIndexOutOfBoundsException | NumberFormatException x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Exception has occured while trying to parse Chunk: " + chunk);
}
Iterator<Map.Entry<Location, Location>> moves = movingQueue.entrySet().iterator();
while (moves.hasNext()) {
Map.Entry<Location, Location> entry = moves.next();
BlockStorage.moveLocationInfoUnsafely(entry.getKey(), entry.getValue());
moves.remove();
}
// Start a new tick cycle for every BlockTicker
for (BlockTicker ticker : tickers) {
ticker.startNewTick();
}
reset();
SlimefunPlugin.getProfiler().stop();
}
catch (Exception | LinkageError x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Exception was caught while ticking the Block Tickers Task for Slimefun v" + SlimefunPlugin.getVersion());
reset();
}
}
private void tickChunk(Set<BlockTicker> tickers, String chunk) {
try {
Set<Location> locations = BlockStorage.getTickingLocations(chunk);
String[] components = PatternUtils.SEMICOLON.split(chunk);
World world = Bukkit.getWorld(components[0]);
int x = Integer.parseInt(components[components.length - 2]);
int z = Integer.parseInt(components[components.length - 1]);
if (world != null && world.isChunkLoaded(x, z)) {
for (Location l : locations) {
tickLocation(tickers, l);
}
}
}
Iterator<Map.Entry<Location, Location>> moves = movingQueue.entrySet().iterator();
while (moves.hasNext()) {
Map.Entry<Location, Location> entry = moves.next();
BlockStorage.moveLocationInfoUnsafely(entry.getKey(), entry.getValue());
moves.remove();
catch (ArrayIndexOutOfBoundsException | NumberFormatException x) {
Slimefun.getLogger().log(Level.SEVERE, x, () -> "An Exception has occured while trying to parse Chunk: " + chunk);
}
Iterator<BlockTicker> iterator = tickers.iterator();
while (iterator.hasNext()) {
iterator.next().startNewTick();
iterator.remove();
}
running = false;
SlimefunPlugin.getProfiler().stop();
}
private void tick(Location l) {
private void tickLocation(Set<BlockTicker> tickers, Location l) {
Config data = BlockStorage.getLocationInfo(l);
SlimefunItem item = SlimefunItem.getByID(data.getString("id"));
@ -170,11 +208,6 @@ public class TickerTask implements Runnable {
halted = true;
}
@Override
public String toString() {
return "TickerTask {\n" + " HALTED = " + halted + "\n" + " tickers = " + tickers + "\n" + " move = " + movingQueue + "\n" + " delete = " + deletionQueue + "}";
}
public void queueMove(Location from, Location to) {
movingQueue.put(from, to);
}
@ -183,22 +216,13 @@ public class TickerTask implements Runnable {
deletionQueue.put(l, destroy);
}
public void start(SlimefunPlugin plugin) {
this.tickRate = SlimefunPlugin.getCfg().getInt("URID.custom-ticker-delay");
plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, () -> {
try {
run();
}
catch (Exception | LinkageError x) {
plugin.getLogger().log(Level.SEVERE, x, () -> "An Exception was caught while ticking the Block Tickers Task for Slimefun v" + SlimefunPlugin.getVersion());
abortTick();
}
}, 100L, tickRate);
}
public int getTickRate() {
return tickRate;
}
@Override
public String toString() {
return "TickerTask {\n" + " HALTED = " + halted + "\n" + " move = " + movingQueue + "\n" + " delete = " + deletionQueue + "}";
}
}

View File

@ -3,6 +3,8 @@ package io.github.thebusybiscuit.slimefun4.utils;
import java.util.Locale;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@ -22,7 +24,7 @@ public final class ChatUtils {
private ChatUtils() {}
public static void sendURL(CommandSender sender, String url) {
public static void sendURL(@Nonnull CommandSender sender, @Nonnull String url) {
// If we get access to the URL prompt one day, we can just prompt the link to the Player that way.
sender.sendMessage("");
SlimefunPlugin.getLocalization().sendMessage(sender, "messages.link-prompt", false);
@ -30,11 +32,11 @@ public final class ChatUtils {
sender.sendMessage("");
}
public static String removeColorCodes(String string) {
public static String removeColorCodes(@Nonnull String string) {
return ChatColor.stripColor(ChatColors.color(string));
}
public static String crop(ChatColor color, String string) {
public static String crop(@Nonnull ChatColor color, @Nonnull String string) {
if (ChatColor.stripColor(color + string).length() > 19) {
return (color + ChatColor.stripColor(string)).substring(0, 18) + "...";
}
@ -43,11 +45,11 @@ public final class ChatUtils {
}
}
public static String christmas(String text) {
public static String christmas(@Nonnull String text) {
return ChatColors.alternating(text, ChatColor.GREEN, ChatColor.RED);
}
public static void awaitInput(Player p, Consumer<String> callback) {
public static void awaitInput(@Nonnull Player p, @Nonnull Consumer<String> callback) {
ChatInput.waitForPlayer(SlimefunPlugin.instance(), p, callback);
}
@ -64,7 +66,7 @@ public final class ChatUtils {
*
* @return A human-friendly version of the given {@link String}
*/
public static String humanize(String string) {
public static String humanize(@Nonnull String string) {
StringBuilder builder = new StringBuilder();
String[] segments = PatternUtils.UNDERSCORE.split(string.toLowerCase(Locale.ROOT));

View File

@ -3,6 +3,8 @@ package io.github.thebusybiscuit.slimefun4.utils;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.Nonnull;
import org.bukkit.ChatColor;
import org.bukkit.Color;
import org.bukkit.FireworkEffect;
@ -25,11 +27,11 @@ public final class FireworkUtils {
private FireworkUtils() {}
public static void launchFirework(Location l, Color color) {
public static void launchFirework(@Nonnull Location l, @Nonnull Color color) {
createFirework(l, color);
}
public static Firework createFirework(Location l, Color color) {
public static Firework createFirework(@Nonnull Location l, @Nonnull Color color) {
Firework fw = (Firework) l.getWorld().spawnEntity(l, EntityType.FIREWORK);
FireworkMeta meta = fw.getFireworkMeta();
@ -42,7 +44,7 @@ public final class FireworkUtils {
return fw;
}
public static void launchRandom(Entity n, int amount) {
public static void launchRandom(@Nonnull Entity n, int amount) {
Random random = ThreadLocalRandom.current();
for (int i = 0; i < amount; i++) {
@ -54,7 +56,7 @@ public final class FireworkUtils {
}
}
public static FireworkEffect getRandomEffect(Random random, Color color) {
public static FireworkEffect getRandomEffect(@Nonnull Random random, @Nonnull Color color) {
return FireworkEffect.builder().flicker(random.nextBoolean()).withColor(color).with(random.nextBoolean() ? Type.BALL : Type.BALL_LARGE).trail(random.nextBoolean()).build();
}

View File

@ -1,5 +1,8 @@
package io.github.thebusybiscuit.slimefun4.utils;
import javax.annotation.Nonnull;
import org.apache.commons.lang.Validate;
import org.bukkit.inventory.ItemStack;
/**
@ -108,7 +111,8 @@ public enum HeadTexture {
private final String texture;
HeadTexture(String texture) {
HeadTexture(@Nonnull String texture) {
Validate.notNull(texture, "Texture cannot be null");
this.texture = texture;
}

View File

@ -6,6 +6,10 @@ import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Locale;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
public final class NumberUtils {
@ -18,7 +22,8 @@ public final class NumberUtils {
return NumberFormat.getNumberInstance(Locale.US).format(i);
}
public static LocalDateTime parseGitHubDate(String date) {
public static LocalDateTime parseGitHubDate(@Nonnull String date) {
Validate.notNull(date, "Provided date was null");
return LocalDateTime.parse(date.substring(0, date.length() - 1));
}
@ -31,7 +36,8 @@ public final class NumberUtils {
else return ChatColor.GREEN;
}
public static String getElapsedTime(LocalDateTime date) {
public static String getElapsedTime(@Nonnull LocalDateTime date) {
Validate.notNull(date, "Provided date was null");
long hours = Duration.between(date, LocalDateTime.now()).toHours();
if (hours == 0) {
@ -88,15 +94,38 @@ public final class NumberUtils {
return DECIMAL_FORMAT.format(number);
}
public static long getLong(Long value, long defaultValue) {
public static long getLong(@Nullable Long value, long defaultValue) {
return value == null ? defaultValue : value;
}
public static int getInt(Integer value, int defaultValue) {
public static int getInt(@Nullable Integer value, int defaultValue) {
return value == null ? defaultValue : value;
}
public static float getFloat(Float value, float defaultValue) {
public static float getFloat(@Nullable Float value, float defaultValue) {
return value == null ? defaultValue : value;
}
/**
* This method is a combination of Math.min and Math.max, it clamps the given value
* between a minimum and a maximum.
*
* @param min
* The minimum value
* @param value
* The value to clamp
* @param max
* The maximum value
*/
public static int clamp(int min, int value, int max) {
if (value < min) {
return min;
}
else if (value > max) {
return max;
}
else {
return value;
}
}
}

View File

@ -6,9 +6,15 @@ import java.util.Base64;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Block;
import org.bukkit.entity.Item;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
@ -18,6 +24,7 @@ import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import io.github.thebusybiscuit.cscorelib2.item.ImmutableItemMeta;
import io.github.thebusybiscuit.cscorelib2.skull.SkullBlock;
import io.github.thebusybiscuit.cscorelib2.skull.SkullItem;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.api.exceptions.PrematureCodeException;
@ -29,6 +36,7 @@ import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
import me.mrCookieSlime.EmeraldEnchants.EmeraldEnchants;
import me.mrCookieSlime.EmeraldEnchants.ItemEnchantment;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.Slimefun;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
/**
@ -58,7 +66,7 @@ public final class SlimefunUtils {
* The {@link Item} to query
* @return Whether the {@link Item} is excluded from being picked up
*/
public static boolean hasNoPickupFlag(Item item) {
public static boolean hasNoPickupFlag(@Nonnull Item item) {
return item.hasMetadata(NO_PICKUP_METADATA);
}
@ -71,7 +79,7 @@ public final class SlimefunUtils {
* @param context
* The context in which this {@link Item} was flagged
*/
public static void markAsNoPickup(Item item, String context) {
public static void markAsNoPickup(@Nonnull Item item, @Nonnull String context) {
item.setMetadata(NO_PICKUP_METADATA, new FixedMetadataValue(SlimefunPlugin.instance(), context));
}
@ -82,19 +90,15 @@ public final class SlimefunUtils {
* The {@link ItemStack} to check for
* @return Whether the given item is soulbound
*/
public static boolean isSoulbound(ItemStack item) {
public static boolean isSoulbound(@Nullable ItemStack item) {
if (item == null || item.getType() == Material.AIR) {
return false;
}
else {
ItemMeta meta = item.hasItemMeta() ? item.getItemMeta() : null;
if (meta != null && SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
PersistentDataContainer container = meta.getPersistentDataContainer();
if (container.has(SOULBOUND_KEY, PersistentDataType.BYTE)) {
return true;
}
if (hasSoulboundFlag(meta)) {
return true;
}
if (SlimefunPlugin.getThirdPartySupportService().isEmeraldEnchantsInstalled()) {
@ -119,6 +123,18 @@ public final class SlimefunUtils {
}
}
private static boolean hasSoulboundFlag(@Nullable ItemMeta meta) {
if (meta != null && SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
PersistentDataContainer container = meta.getPersistentDataContainer();
if (container.has(SOULBOUND_KEY, PersistentDataType.BYTE)) {
return true;
}
}
return false;
}
/**
* Toggles an {@link ItemStack} to be Soulbound.<br>
* If true is passed, this will add the {@link #SOULBOUND_LORE} and
@ -133,7 +149,7 @@ public final class SlimefunUtils {
*
* @see #isSoulbound(ItemStack)
*/
public static void setSoulbound(ItemStack item, boolean makeSoulbound) {
public static void setSoulbound(@Nullable ItemStack item, boolean makeSoulbound) {
if (item == null || item.getType() == Material.AIR) {
throw new IllegalArgumentException("A soulbound item cannot be null or air!");
}
@ -175,7 +191,7 @@ public final class SlimefunUtils {
*
* @return Whether this {@link ItemStack} is radioactive or not
*/
public static boolean isRadioactive(ItemStack item) {
public static boolean isRadioactive(@Nullable ItemStack item) {
return SlimefunItem.getByItem(item) instanceof Radioactive;
}
@ -185,9 +201,12 @@ public final class SlimefunUtils {
*
* @param texture
* The texture for this head (base64 or hash)
*
* @return An {@link ItemStack} with this Head texture
*/
public static ItemStack getCustomHead(String texture) {
public static ItemStack getCustomHead(@Nonnull String texture) {
Validate.notNull(texture, "The provided texture is null");
if (SlimefunPlugin.instance() == null) {
throw new PrematureCodeException("You cannot instantiate a custom head before Slimefun was loaded.");
}
@ -229,11 +248,11 @@ public final class SlimefunUtils {
return false;
}
public static boolean isItemSimilar(ItemStack item, ItemStack sfitem, boolean checkLore) {
public static boolean isItemSimilar(@Nullable ItemStack item, @Nullable ItemStack sfitem, boolean checkLore) {
return isItemSimilar(item, sfitem, checkLore, true);
}
public static boolean isItemSimilar(ItemStack item, ItemStack sfitem, boolean checkLore, boolean checkAmount) {
public static boolean isItemSimilar(@Nullable ItemStack item, @Nullable ItemStack sfitem, boolean checkLore, boolean checkAmount) {
if (item == null) return sfitem == null;
if (sfitem == null) return false;
if (item.getType() != sfitem.getType()) return false;
@ -267,7 +286,7 @@ public final class SlimefunUtils {
return false;
}
private static boolean equalsItemMeta(ItemMeta itemMeta, ImmutableItemMeta meta, boolean checkLore) {
private static boolean equalsItemMeta(@Nonnull ItemMeta itemMeta, @Nonnull ImmutableItemMeta meta, boolean checkLore) {
Optional<String> displayName = meta.getDisplayName();
if (itemMeta.hasDisplayName() != displayName.isPresent()) {
@ -291,7 +310,7 @@ public final class SlimefunUtils {
}
}
private static boolean equalsItemMeta(ItemMeta itemMeta, ItemMeta sfitemMeta, boolean checkLore) {
private static boolean equalsItemMeta(@Nonnull ItemMeta itemMeta, @Nonnull ItemMeta sfitemMeta, boolean checkLore) {
if (itemMeta.hasDisplayName() != sfitemMeta.hasDisplayName()) {
return false;
}
@ -309,7 +328,7 @@ public final class SlimefunUtils {
}
}
private static boolean equalsLore(List<String> lore, List<String> lore2) {
private static boolean equalsLore(@Nonnull List<String> lore, @Nonnull List<String> lore2) {
StringBuilder string1 = new StringBuilder();
StringBuilder string2 = new StringBuilder();
@ -328,4 +347,30 @@ public final class SlimefunUtils {
return string1.toString().equals(string2.toString());
}
public static void updateCapacitorTexture(@Nonnull Location l, int charge, int capacity) {
Validate.notNull(l, "Cannot update a texture for null");
Validate.isTrue(capacity > 0, "Capacity must be greater than zero!");
Slimefun.runSync(() -> {
Block b = l.getBlock();
if (b.getType() == Material.PLAYER_HEAD || b.getType() == Material.PLAYER_WALL_HEAD) {
double level = (double) charge / capacity;
if (level <= 0.25) {
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_25.getTexture());
}
else if (level <= 0.5) {
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_50.getTexture());
}
else if (level <= 0.75) {
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_75.getTexture());
}
else {
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_100.getTexture());
}
}
});
}
}

View File

@ -9,6 +9,8 @@ import java.util.Set;
import java.util.function.Consumer;
import java.util.logging.Level;
import javax.annotation.Nonnull;
import org.apache.commons.lang.Validate;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@ -27,7 +29,6 @@ import io.github.thebusybiscuit.slimefun4.api.exceptions.UnregisteredItemExcepti
import io.github.thebusybiscuit.slimefun4.api.exceptions.WrongItemStackException;
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
import io.github.thebusybiscuit.slimefun4.api.items.ItemState;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
import io.github.thebusybiscuit.slimefun4.core.attributes.Placeable;
import io.github.thebusybiscuit.slimefun4.core.attributes.Radioactive;
import io.github.thebusybiscuit.slimefun4.core.attributes.Rechargeable;
@ -325,7 +326,7 @@ public class SlimefunItem implements Placeable {
* @param addon
* The {@link SlimefunAddon} that this {@link SlimefunItem} belongs to.
*/
public void register(SlimefunAddon addon) {
public void register(@Nonnull SlimefunAddon addon) {
Validate.notNull(addon, "A SlimefunAddon cannot be null!");
Validate.notNull(addon.getJavaPlugin(), "SlimefunAddon#getJavaPlugin() is not allowed to return null!");
@ -370,14 +371,6 @@ public class SlimefunItem implements Placeable {
SlimefunPlugin.getRegistry().getRadioactiveItems().add(this);
}
if (this instanceof EnergyNetComponent && !SlimefunPlugin.getRegistry().getEnergyCapacities().containsKey(getID())) {
int capacity = ((EnergyNetComponent) this).getCapacity();
if (capacity > 0) {
SlimefunPlugin.getRegistry().getEnergyCapacities().put(id, capacity);
}
}
if (SlimefunPlugin.getItemCfg().getBoolean(id + ".enabled")) {
if (!category.isRegistered()) {

View File

@ -29,7 +29,6 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock;
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
@ -76,14 +75,14 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock,
}
for (int i : BORDER_IN) {
preset.addItem(i, new CustomItem(new ItemStack(Material.CYAN_STAINED_GLASS_PANE), " "), ChestMenuUtils.getEmptyClickHandler());
preset.addItem(i, new CustomItem(Material.CYAN_STAINED_GLASS_PANE, " "), ChestMenuUtils.getEmptyClickHandler());
}
for (int i : BORDER_OUT) {
preset.addItem(i, new CustomItem(new ItemStack(Material.ORANGE_STAINED_GLASS_PANE), " "), ChestMenuUtils.getEmptyClickHandler());
preset.addItem(i, new CustomItem(Material.ORANGE_STAINED_GLASS_PANE, " "), ChestMenuUtils.getEmptyClickHandler());
}
preset.addItem(22, new CustomItem(new ItemStack(Material.BLACK_STAINED_GLASS_PANE), " "), ChestMenuUtils.getEmptyClickHandler());
preset.addItem(22, new CustomItem(Material.BLACK_STAINED_GLASS_PANE, " "), ChestMenuUtils.getEmptyClickHandler());
for (int i : getOutputSlots()) {
preset.addMenuClickHandler(i, new AdvancedMenuClickHandler() {
@ -236,12 +235,12 @@ public abstract class AContainer extends SlimefunItem implements InventoryBlock,
if (timeleft > 0) {
ChestMenuUtils.updateProgressbar(inv, 22, timeleft, processing.get(b).getTicks(), getProgressBar());
if (getCapacity() > 0) {
if (ChargableBlock.getCharge(b) < getEnergyConsumption()) {
if (isChargeable()) {
if (getCharge(b.getLocation()) < getEnergyConsumption()) {
return;
}
ChargableBlock.addCharge(b, -getEnergyConsumption());
removeCharge(b.getLocation(), getEnergyConsumption());
progress.put(b, timeleft - 1);
}
else {

View File

@ -25,7 +25,6 @@ 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.energy.ChargableBlock;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
@ -133,7 +132,6 @@ public abstract class AGenerator extends AbstractEnergyProvider {
@Override
public int getGeneratedOutput(Location l, Config data) {
BlockMenu inv = BlockStorage.getInventory(l);
boolean chargeable = getCapacity() > 0;
if (isProcessing(l)) {
int timeleft = progress.get(l);
@ -141,8 +139,8 @@ public abstract class AGenerator extends AbstractEnergyProvider {
if (timeleft > 0) {
ChestMenuUtils.updateProgressbar(inv, 22, timeleft, processing.get(l).getTicks(), getProgressBar());
if (chargeable) {
int charge = ChargableBlock.getCharge(l);
if (isChargeable()) {
int charge = getCharge(l);
if (getCapacity() - charge >= getEnergyProduction()) {
progress.put(l, timeleft - 1);

View File

@ -1,17 +1,20 @@
package me.mrCookieSlime.Slimefun.api.energy;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import io.github.thebusybiscuit.cscorelib2.skull.SkullBlock;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.Capacitor;
import io.github.thebusybiscuit.slimefun4.utils.HeadTexture;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
*
* @deprecated Use the methods provided by {@link EnergyNetComponent} instead.
*
*/
@Deprecated
public final class ChargableBlock {
private static final String KEY = "energy-charge";
@ -23,13 +26,8 @@ public final class ChargableBlock {
}
public static boolean isChargable(Location l) {
String id = BlockStorage.checkID(l);
if (id == null) {
return false;
}
return SlimefunPlugin.getRegistry().getEnergyCapacities().containsKey(id);
SlimefunItem item = BlockStorage.check(l);
return item instanceof EnergyNetComponent && ((EnergyNetComponent) item).isChargeable();
}
public static int getCharge(Block b) {
@ -70,7 +68,7 @@ public final class ChargableBlock {
BlockStorage.addBlockInfo(l, KEY, String.valueOf(charge), false);
if (updateTexture) {
updateCapacitor(l, charge, getMaxCharge(l));
SlimefunUtils.updateCapacitorTexture(l, charge, getMaxCharge(l));
}
}
}
@ -80,14 +78,14 @@ public final class ChargableBlock {
}
public static int addCharge(Location l, int addedCharge) {
String id = BlockStorage.checkID(l);
SlimefunItem item = BlockStorage.check(l);
if (id == null) {
if (item == null) {
BlockStorage.clearBlockInfo(l);
return 0;
}
int capacity = SlimefunPlugin.getRegistry().getEnergyCapacities().getOrDefault(id, 0);
int capacity = ((EnergyNetComponent) item).getCapacity();
int charge = getCharge(l);
int availableSpace = capacity - charge;
@ -105,56 +103,36 @@ public final class ChargableBlock {
setCharge(l, charge);
if (SlimefunItem.getByID(id) instanceof Capacitor) {
updateCapacitor(l, charge, capacity);
if (item instanceof Capacitor) {
SlimefunUtils.updateCapacitorTexture(l, charge, capacity);
}
}
else if (addedCharge < 0 && charge >= -addedCharge) {
charge += addedCharge;
setCharge(l, charge);
if (SlimefunItem.getByID(id) instanceof Capacitor) {
updateCapacitor(l, charge, capacity);
if (item instanceof Capacitor) {
SlimefunUtils.updateCapacitorTexture(l, charge, capacity);
}
}
return rest;
}
private static void updateCapacitor(Location l, int charge, int capacity) {
Slimefun.runSync(() -> {
Block b = l.getBlock();
if (b.getType() == Material.PLAYER_HEAD || b.getType() == Material.PLAYER_WALL_HEAD) {
if (charge < (int) (capacity * 0.25)) {
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_25.getTexture());
}
else if (charge < (int) (capacity * 0.5)) {
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_50.getTexture());
}
else if (charge < (int) (capacity * 0.75)) {
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_75.getTexture());
}
else {
SkullBlock.setFromHash(b, HeadTexture.CAPACITOR_100.getTexture());
}
}
});
}
public static int getMaxCharge(Block b) {
return getMaxCharge(b.getLocation());
}
public static int getMaxCharge(Location l) {
String id = BlockStorage.checkID(l);
SlimefunItem item = BlockStorage.check(l);
if (id == null) {
if (item == null) {
BlockStorage.clearBlockInfo(l);
return 0;
}
return SlimefunPlugin.getRegistry().getEnergyCapacities().getOrDefault(id, 0);
return item instanceof EnergyNetComponent ? ((EnergyNetComponent) item).getCapacity() : 0;
}
}