mirror of
https://github.com/StarWishsama/Slimefun4.git
synced 2024-09-19 19:25:48 +00:00
Lots of refactoring
This commit is contained in:
parent
22650f53dd
commit
7acee959ce
@ -28,6 +28,7 @@
|
|||||||
* Added Advanced Industrial Miner
|
* Added Advanced Industrial Miner
|
||||||
* Added Cocoa Organic Food
|
* Added Cocoa Organic Food
|
||||||
* Added Cocoa Fertilizer
|
* Added Cocoa Fertilizer
|
||||||
|
* Added a configurable limit to the Pickaxe of Vein Mining
|
||||||
|
|
||||||
#### Changes
|
#### Changes
|
||||||
* Fixed a few memory leaks
|
* Fixed a few memory leaks
|
||||||
@ -36,6 +37,7 @@
|
|||||||
* Dried Kelp Blocks can now be used in the Coal Generator
|
* Dried Kelp Blocks can now be used in the Coal Generator
|
||||||
* Crafting Organic Food/Fertilizer yields more output now
|
* Crafting Organic Food/Fertilizer yields more output now
|
||||||
* Organic Food (Melon) now uses Melon Slices instead of Melon blocks
|
* Organic Food (Melon) now uses Melon Slices instead of Melon blocks
|
||||||
|
* The Seismic Axe now skips the first two blocks to clear your field of view
|
||||||
|
|
||||||
#### Fixes
|
#### Fixes
|
||||||
* Fixed Ore Washer recipes showing up twice
|
* Fixed Ore Washer recipes showing up twice
|
||||||
|
@ -47,29 +47,41 @@ class GiveCommand extends SubCommand {
|
|||||||
SlimefunItem sfItem = SlimefunItem.getByID(args[2].toUpperCase(Locale.ROOT));
|
SlimefunItem sfItem = SlimefunItem.getByID(args[2].toUpperCase(Locale.ROOT));
|
||||||
|
|
||||||
if (sfItem != null) {
|
if (sfItem != null) {
|
||||||
if (sfItem instanceof MultiBlockMachine) {
|
giveItem(sender, p, sfItem, args);
|
||||||
SlimefunPlugin.getLocal().sendMessage(sender, "guide.cheat.no-multiblocks");
|
}
|
||||||
}
|
else {
|
||||||
else {
|
SlimefunPlugin.getLocal().sendMessage(sender, "messages.not-valid-item", true, msg -> msg.replace(PLACEHOLDER_ITEM, args[2]));
|
||||||
int amount = parseAmount(args);
|
|
||||||
|
|
||||||
if (amount > 0) {
|
|
||||||
SlimefunPlugin.getLocal().sendMessage(p, "messages.given-item", true, msg -> msg.replace(PLACEHOLDER_ITEM, sfItem.getItemName()).replace(PLACEHOLDER_AMOUNT, String.valueOf(amount)));
|
|
||||||
p.getInventory().addItem(new CustomItem(sfItem.getItem(), amount));
|
|
||||||
SlimefunPlugin.getLocal().sendMessage(sender, "messages.give-item", true, msg -> msg.replace(PLACEHOLDER_PLAYER, args[1]).replace(PLACEHOLDER_ITEM, sfItem.getItemName()).replace(PLACEHOLDER_AMOUNT, String.valueOf(amount)));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SlimefunPlugin.getLocal().sendMessage(sender, "messages.not-valid-amount", true, msg -> msg.replace(PLACEHOLDER_AMOUNT, args[3]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else SlimefunPlugin.getLocal().sendMessage(sender, "messages.not-valid-item", true, msg -> msg.replace(PLACEHOLDER_ITEM, args[2]));
|
|
||||||
}
|
}
|
||||||
else SlimefunPlugin.getLocal().sendMessage(sender, "messages.not-online", true, msg -> msg.replace(PLACEHOLDER_PLAYER, args[1]));
|
else {
|
||||||
|
SlimefunPlugin.getLocal().sendMessage(sender, "messages.not-online", true, msg -> msg.replace(PLACEHOLDER_PLAYER, args[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SlimefunPlugin.getLocal().sendMessage(sender, "messages.usage", true, msg -> msg.replace("%usage%", "/sf give <Player> <Slimefun Item> [Amount]"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SlimefunPlugin.getLocal().sendMessage(sender, "messages.no-permission", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void giveItem(CommandSender sender, Player p, SlimefunItem sfItem, String[] args) {
|
||||||
|
if (sfItem instanceof MultiBlockMachine) {
|
||||||
|
SlimefunPlugin.getLocal().sendMessage(sender, "guide.cheat.no-multiblocks");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int amount = parseAmount(args);
|
||||||
|
|
||||||
|
if (amount > 0) {
|
||||||
|
SlimefunPlugin.getLocal().sendMessage(p, "messages.given-item", true, msg -> msg.replace(PLACEHOLDER_ITEM, sfItem.getItemName()).replace(PLACEHOLDER_AMOUNT, String.valueOf(amount)));
|
||||||
|
p.getInventory().addItem(new CustomItem(sfItem.getItem(), amount));
|
||||||
|
SlimefunPlugin.getLocal().sendMessage(sender, "messages.give-item", true, msg -> msg.replace(PLACEHOLDER_PLAYER, args[1]).replace(PLACEHOLDER_ITEM, sfItem.getItemName()).replace(PLACEHOLDER_AMOUNT, String.valueOf(amount)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SlimefunPlugin.getLocal().sendMessage(sender, "messages.not-valid-amount", true, msg -> msg.replace(PLACEHOLDER_AMOUNT, args[3]));
|
||||||
}
|
}
|
||||||
else SlimefunPlugin.getLocal().sendMessage(sender, "messages.usage", true, msg -> msg.replace("%usage%", "/sf give <Player> <Slimefun Item> [Amount]"));
|
|
||||||
}
|
}
|
||||||
else SlimefunPlugin.getLocal().sendMessage(sender, "messages.no-permission", true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int parseAmount(String[] args) {
|
private int parseAmount(String[] args) {
|
||||||
|
@ -35,8 +35,12 @@ class GitHubIssuesTracker extends GitHubConnector {
|
|||||||
for (JsonElement elem : array) {
|
for (JsonElement elem : array) {
|
||||||
JsonObject obj = elem.getAsJsonObject();
|
JsonObject obj = elem.getAsJsonObject();
|
||||||
|
|
||||||
if (obj.has("pull_request")) pullRequests++;
|
if (obj.has("pull_request")) {
|
||||||
else issues++;
|
pullRequests++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
issues++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callback.update(issues, pullRequests);
|
callback.update(issues, pullRequests);
|
||||||
|
@ -45,52 +45,18 @@ class GitHubTask implements Runnable {
|
|||||||
// Store all queried usernames to prevent 429 responses for pinging the
|
// Store all queried usernames to prevent 429 responses for pinging the
|
||||||
// same URL twice in one run.
|
// same URL twice in one run.
|
||||||
Map<String, String> skins = new HashMap<>();
|
Map<String, String> skins = new HashMap<>();
|
||||||
int count = 0;
|
int requests = 0;
|
||||||
|
|
||||||
for (Contributor contributor : gitHubService.getContributors().values()) {
|
for (Contributor contributor : gitHubService.getContributors().values()) {
|
||||||
if (!contributor.hasTexture()) {
|
int newRequests = requestTexture(contributor, skins);
|
||||||
try {
|
requests += newRequests;
|
||||||
if (skins.containsKey(contributor.getMinecraftName())) {
|
|
||||||
contributor.setTexture(skins.get(contributor.getMinecraftName()));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
contributor.setTexture(grabTexture(skins, contributor));
|
|
||||||
|
|
||||||
count += contributor.getUniqueId().isPresent() ? 1 : 2;
|
if (newRequests < 0 || requests >= MAX_REQUESTS_PER_MINUTE) {
|
||||||
|
break;
|
||||||
if (count >= MAX_REQUESTS_PER_MINUTE) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (IllegalArgumentException x) {
|
|
||||||
// There cannot be a texture found because it is not a valid MC username
|
|
||||||
contributor.setTexture(null);
|
|
||||||
}
|
|
||||||
catch (IOException x) {
|
|
||||||
// Too many requests
|
|
||||||
Slimefun.getLogger().log(Level.WARNING, "Attempted to connect to mojang.com, got this response: {0}: {1}", new Object[] { x.getClass().getSimpleName(), x.getMessage() });
|
|
||||||
Slimefun.getLogger().log(Level.WARNING, "This usually means mojang.com is down or started to rate-limit this connection, this is not an error message!");
|
|
||||||
|
|
||||||
// Retry after 5 minutes if it was rate-limiting
|
|
||||||
if (x.getMessage().contains("429")) {
|
|
||||||
Bukkit.getScheduler().runTaskLaterAsynchronously(SlimefunPlugin.instance, this::grabTextures, 5 * 60 * 20L);
|
|
||||||
}
|
|
||||||
|
|
||||||
count = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch (TooManyRequestsException x) {
|
|
||||||
Slimefun.getLogger().log(Level.WARNING, "Received a rate-limit from mojang.com, retrying in 4 minutes");
|
|
||||||
Bukkit.getScheduler().runTaskLaterAsynchronously(SlimefunPlugin.instance, this::grabTextures, 4 * 60 * 20L);
|
|
||||||
|
|
||||||
count = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count >= MAX_REQUESTS_PER_MINUTE) {
|
if (requests >= MAX_REQUESTS_PER_MINUTE) {
|
||||||
// Slow down API requests and wait a minute after more than x requests were made
|
// Slow down API requests and wait a minute after more than x requests were made
|
||||||
Bukkit.getScheduler().runTaskLaterAsynchronously(SlimefunPlugin.instance, this::grabTextures, 2 * 60 * 20L);
|
Bukkit.getScheduler().runTaskLaterAsynchronously(SlimefunPlugin.instance, this::grabTextures, 2 * 60 * 20L);
|
||||||
}
|
}
|
||||||
@ -106,7 +72,45 @@ class GitHubTask implements Runnable {
|
|||||||
gitHubService.saveUUIDCache();
|
gitHubService.saveUUIDCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String grabTexture(Map<String, String> skins, Contributor contributor) throws TooManyRequestsException, IOException {
|
private int requestTexture(Contributor contributor, Map<String, String> skins) {
|
||||||
|
if (!contributor.hasTexture()) {
|
||||||
|
try {
|
||||||
|
if (skins.containsKey(contributor.getMinecraftName())) {
|
||||||
|
contributor.setTexture(skins.get(contributor.getMinecraftName()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
contributor.setTexture(pullTexture(skins, contributor));
|
||||||
|
return contributor.getUniqueId().isPresent() ? 1 : 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException x) {
|
||||||
|
// There cannot be a texture found because it is not a valid MC username
|
||||||
|
contributor.setTexture(null);
|
||||||
|
}
|
||||||
|
catch (IOException x) {
|
||||||
|
// Too many requests
|
||||||
|
Slimefun.getLogger().log(Level.WARNING, "Attempted to connect to mojang.com, got this response: {0}: {1}", new Object[] { x.getClass().getSimpleName(), x.getMessage() });
|
||||||
|
Slimefun.getLogger().log(Level.WARNING, "This usually means mojang.com is down or started to rate-limit this connection, this is not an error message!");
|
||||||
|
|
||||||
|
// Retry after 5 minutes if it was rate-limiting
|
||||||
|
if (x.getMessage().contains("429")) {
|
||||||
|
Bukkit.getScheduler().runTaskLaterAsynchronously(SlimefunPlugin.instance, this::grabTextures, 5 * 60 * 20L);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
catch (TooManyRequestsException x) {
|
||||||
|
Slimefun.getLogger().log(Level.WARNING, "Received a rate-limit from mojang.com, retrying in 4 minutes");
|
||||||
|
Bukkit.getScheduler().runTaskLaterAsynchronously(SlimefunPlugin.instance, this::grabTextures, 4 * 60 * 20L);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String pullTexture(Map<String, String> skins, Contributor contributor) throws TooManyRequestsException, IOException {
|
||||||
Optional<UUID> uuid = contributor.getUniqueId();
|
Optional<UUID> uuid = contributor.getUniqueId();
|
||||||
|
|
||||||
if (!uuid.isPresent()) {
|
if (!uuid.isPresent()) {
|
||||||
|
@ -1,490 +0,0 @@
|
|||||||
package io.github.thebusybiscuit.slimefun4.implementation.items.androids;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.ChatColor;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.OfflinePlayer;
|
|
||||||
import org.bukkit.Sound;
|
|
||||||
import org.bukkit.block.Block;
|
|
||||||
import org.bukkit.block.BlockFace;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import io.github.thebusybiscuit.cscorelib2.chat.ChatInput;
|
|
||||||
import io.github.thebusybiscuit.cscorelib2.config.Config;
|
|
||||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
|
||||||
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
|
|
||||||
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
|
|
||||||
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
|
||||||
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
|
|
||||||
import me.mrCookieSlime.Slimefun.SlimefunPlugin;
|
|
||||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
|
||||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
|
||||||
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.inventory.BlockMenu;
|
|
||||||
|
|
||||||
abstract class Android extends SlimefunItem {
|
|
||||||
|
|
||||||
public Android(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
|
||||||
super(category, item, recipeType, recipe);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This returns the {@link AndroidType} that is associated with this {@link ProgrammableAndroid}.
|
|
||||||
*
|
|
||||||
* @return The type of this {@link ProgrammableAndroid}
|
|
||||||
*/
|
|
||||||
public abstract AndroidType getAndroidType();
|
|
||||||
|
|
||||||
protected abstract void tick(Block b);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void preRegister() {
|
|
||||||
super.preRegister();
|
|
||||||
|
|
||||||
addItemHandler(new BlockTicker() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tick(Block b, SlimefunItem sf, me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config data) {
|
|
||||||
if (b != null) {
|
|
||||||
Android.this.tick(b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSynchronized() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void killEntities(Block b, double damage, Predicate<Entity> predicate) {
|
|
||||||
throw new UnsupportedOperationException("Non-butcher Android tried to butcher!");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void fish(Block b, BlockMenu menu) {
|
|
||||||
throw new UnsupportedOperationException("Non-fishing Android tried to fish!");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void mine(Block b, BlockMenu menu, Block block) {
|
|
||||||
throw new UnsupportedOperationException("Non-mining Android tried to mine!");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void movedig(Block b, BlockMenu menu, BlockFace face, Block block) {
|
|
||||||
throw new UnsupportedOperationException("Non-mining Android tried to mine!");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean chopTree(Block b, BlockMenu menu, BlockFace face) {
|
|
||||||
throw new UnsupportedOperationException("Non-woodcutter Android tried to chop a Tree!");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void farm(BlockMenu menu, Block block) {
|
|
||||||
throw new UnsupportedOperationException("Non-farming Android tried to farm!");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void exoticFarm(BlockMenu menu, Block block) {
|
|
||||||
throw new UnsupportedOperationException("Non-farming Android tried to farm!");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void openScript(Player p, Block b, String script) {
|
|
||||||
ChestMenu menu = new ChestMenu(ChatColor.DARK_AQUA + SlimefunPlugin.getLocal().getMessage(p, "android.scripts.editor"));
|
|
||||||
|
|
||||||
menu.addItem(0, new CustomItem(ScriptAction.START.getItem(), SlimefunPlugin.getLocal().getMessage(p, "android.scripts.instructions.START"), "", "&7\u21E8 &eLeft Click &7to return to the Android's interface"));
|
|
||||||
menu.addMenuClickHandler(0, (pl, slot, item, action) -> {
|
|
||||||
BlockStorage.getInventory(b).open(pl);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
String[] commands = PatternUtils.DASH.split(script);
|
|
||||||
|
|
||||||
for (int i = 1; i < commands.length; i++) {
|
|
||||||
int index = i;
|
|
||||||
|
|
||||||
if (i == commands.length - 1) {
|
|
||||||
int additional = commands.length == 54 ? 0 : 1;
|
|
||||||
|
|
||||||
if (additional == 1) {
|
|
||||||
menu.addItem(i, new CustomItem(SlimefunUtils.getCustomHead("171d8979c1878a05987a7faf21b56d1b744f9d068c74cffcde1ea1edad5852"), "&7> Add new Command"));
|
|
||||||
menu.addMenuClickHandler(i, (pl, slot, item, action) -> {
|
|
||||||
openScriptComponentEditor(pl, b, script, index);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
menu.addItem(i + additional, new CustomItem(ScriptAction.REPEAT.getItem(), SlimefunPlugin.getLocal().getMessage(p, "android.scripts.instructions.REPEAT"), "", "&7\u21E8 &eLeft Click &7to return to the Android's interface"));
|
|
||||||
menu.addMenuClickHandler(i + additional, (pl, slot, item, action) -> {
|
|
||||||
BlockStorage.getInventory(b).open(pl);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ItemStack stack = ScriptAction.valueOf(commands[i]).getItem();
|
|
||||||
menu.addItem(i, new CustomItem(stack, SlimefunPlugin.getLocal().getMessage(p, "android.scripts.instructions." + ScriptAction.valueOf(commands[i]).name()), "", "&7\u21E8 &eLeft Click &7to edit", "&7\u21E8 &eRight Click &7to delete", "&7\u21E8 &eShift + Right Click &7to duplicate"));
|
|
||||||
menu.addMenuClickHandler(i, (pl, slot, item, action) -> {
|
|
||||||
if (action.isRightClicked() && action.isShiftClicked()) {
|
|
||||||
if (commands.length == 54) return false;
|
|
||||||
|
|
||||||
int j = 0;
|
|
||||||
StringBuilder builder = new StringBuilder(ScriptAction.START + "-");
|
|
||||||
|
|
||||||
for (String command : commands) {
|
|
||||||
if (j > 0) {
|
|
||||||
if (j == index) {
|
|
||||||
builder.append(commands[j]).append('-').append(commands[j]).append('-');
|
|
||||||
}
|
|
||||||
else if (j < commands.length - 1) builder.append(command).append('-');
|
|
||||||
}
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
builder.append(ScriptAction.REPEAT);
|
|
||||||
setScript(b.getLocation(), builder.toString());
|
|
||||||
openScript(pl, b, builder.toString());
|
|
||||||
}
|
|
||||||
else if (action.isRightClicked()) {
|
|
||||||
int j = 0;
|
|
||||||
StringBuilder builder = new StringBuilder(ScriptAction.START + "-");
|
|
||||||
|
|
||||||
for (String command : commands) {
|
|
||||||
if (j != index && j > 0 && j < commands.length - 1) builder.append(command).append('-');
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.append(ScriptAction.REPEAT);
|
|
||||||
setScript(b.getLocation(), builder.toString());
|
|
||||||
|
|
||||||
openScript(pl, b, builder.toString());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
openScriptComponentEditor(pl, b, script, index);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
menu.open(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void openScriptDownloader(Player p, Block b, int page) {
|
|
||||||
ChestMenu menu = new ChestMenu("Android Scripts");
|
|
||||||
menu.addMenuOpeningHandler(pl -> pl.playSound(pl.getLocation(), Sound.BLOCK_NOTE_BLOCK_HAT, 0.7F, 0.7F));
|
|
||||||
|
|
||||||
List<Config> scripts = getUploadedScripts();
|
|
||||||
|
|
||||||
int pages = (scripts.size() / 45) + 1;
|
|
||||||
|
|
||||||
for (int i = 45; i < 54; i++) {
|
|
||||||
menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
|
|
||||||
menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
|
|
||||||
}
|
|
||||||
|
|
||||||
menu.addItem(46, new CustomItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), "&r\u21E6 Previous Page", "", "&7(" + page + " / " + pages + ")"));
|
|
||||||
menu.addMenuClickHandler(46, (pl, slot, item, action) -> {
|
|
||||||
int next = page - 1;
|
|
||||||
if (next < 1) next = pages;
|
|
||||||
if (next != page) {
|
|
||||||
openScriptDownloader(pl, b, next);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
menu.addItem(48, new CustomItem(SlimefunUtils.getCustomHead("105a2cab8b68ea57e3af992a36e47c8ff9aa87cc8776281966f8c3cf31a38"), "&eUpload a Script", "", "&6Click &7to upload your Android's Script", "&7to the Database"));
|
|
||||||
menu.addMenuClickHandler(48, (pl, slot, item, action) -> {
|
|
||||||
uploadScript(pl, b, page);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
menu.addItem(50, new CustomItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), "&rNext Page \u21E8", "", "&7(" + page + " / " + pages + ")"));
|
|
||||||
menu.addMenuClickHandler(50, (pl, slot, item, action) -> {
|
|
||||||
int next = page + 1;
|
|
||||||
if (next > pages) next = 1;
|
|
||||||
if (next != page) {
|
|
||||||
openScriptDownloader(pl, b, next);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
menu.addItem(53, new CustomItem(SlimefunUtils.getCustomHead("185c97dbb8353de652698d24b64327b793a3f32a98be67b719fbedab35e"), "&6> Back", "", "&7Return to the Android's interface"));
|
|
||||||
menu.addMenuClickHandler(53, (pl, slot, item, action) -> {
|
|
||||||
openScriptEditor(pl, b);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
int categoryIndex = 45 * (page - 1);
|
|
||||||
|
|
||||||
for (int i = 0; i < 45; i++) {
|
|
||||||
int target = categoryIndex + i;
|
|
||||||
|
|
||||||
if (target >= scripts.size()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Config script = scripts.get(target);
|
|
||||||
|
|
||||||
OfflinePlayer op = Bukkit.getOfflinePlayer(script.getUUID("author"));
|
|
||||||
String author = (op != null && op.getName() != null) ? op.getName() : script.getString("author_name");
|
|
||||||
|
|
||||||
if (script.getString("author").equals(p.getUniqueId().toString())) {
|
|
||||||
menu.addItem(index, new CustomItem(this.getItem(), "&b" + script.getString("name"), "&7by &r" + author, "", "&7Downloads: &r" + script.getInt("downloads"), "&7Rating: " + getScriptRatingPercentage(script), "&a" + getScriptRating(script, true) + " \u263A &7| &4\u2639 " + getScriptRating(script, false), "", "&eLeft Click &rto download this Script", "&4(This will override your current Script)"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
menu.addItem(index, new CustomItem(this.getItem(), "&b" + script.getString("name"), "&7by &r" + author, "", "&7Downloads: &r" + script.getInt("downloads"), "&7Rating: " + getScriptRatingPercentage(script), "&a" + getScriptRating(script, true) + " \u263A &7| &4\u2639 " + getScriptRating(script, false), "", "&eLeft Click &rto download this Script", "&4(This will override your current Script)", "&eShift + Left Click &rto leave a positive Rating", "&eShift + Right Click &rto leave a negative Rating"));
|
|
||||||
}
|
|
||||||
|
|
||||||
menu.addMenuClickHandler(index, (pl, slot, item, action) -> {
|
|
||||||
Config script2 = new Config(script.getFile());
|
|
||||||
|
|
||||||
if (action.isShiftClicked()) {
|
|
||||||
if (script2.getString("author").equals(pl.getUniqueId().toString())) {
|
|
||||||
SlimefunPlugin.getLocal().sendMessage(pl, "android.scripts.rating.own", true);
|
|
||||||
}
|
|
||||||
else if (action.isRightClicked()) {
|
|
||||||
if (!script2.getStringList("rating.negative").contains(pl.getUniqueId().toString()) && !script2.getStringList("rating.positive").contains(pl.getUniqueId().toString())) {
|
|
||||||
List<String> list = script2.getStringList("rating.negative");
|
|
||||||
list.add(p.getUniqueId().toString());
|
|
||||||
|
|
||||||
script2.setValue("rating.negative", list);
|
|
||||||
script2.save();
|
|
||||||
|
|
||||||
openScriptDownloader(pl, b, page);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SlimefunPlugin.getLocal().sendMessage(pl, "android.scripts.rating.already", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!script2.getStringList("rating.negative").contains(pl.getUniqueId().toString()) && !script2.getStringList("rating.positive").contains(pl.getUniqueId().toString())) {
|
|
||||||
List<String> list = script2.getStringList("rating.positive");
|
|
||||||
list.add(pl.getUniqueId().toString());
|
|
||||||
|
|
||||||
script2.setValue("rating.positive", list);
|
|
||||||
script2.save();
|
|
||||||
|
|
||||||
openScriptDownloader(pl, b, page);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
SlimefunPlugin.getLocal().sendMessage(pl, "android.scripts.rating.already", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!action.isRightClicked()) {
|
|
||||||
script2.setValue("downloads", script2.getInt("downloads") + 1);
|
|
||||||
script2.save();
|
|
||||||
|
|
||||||
setScript(b.getLocation(), script2.getString("code"));
|
|
||||||
openScriptEditor(pl, b);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
menu.open(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void uploadScript(Player p, Block b, int page) {
|
|
||||||
String code = getScript(b.getLocation());
|
|
||||||
int num = 1;
|
|
||||||
|
|
||||||
for (Config script : getUploadedScripts()) {
|
|
||||||
if (script.getString("author").equals(p.getUniqueId().toString())) {
|
|
||||||
num++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (script.getString("code").equals(code)) {
|
|
||||||
SlimefunPlugin.getLocal().sendMessage(p, "android.scripts.already-uploaded", true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int id = num;
|
|
||||||
|
|
||||||
p.closeInventory();
|
|
||||||
SlimefunPlugin.getLocal().sendMessages(p, "android.scripts.enter-name");
|
|
||||||
|
|
||||||
ChatInput.waitForPlayer(SlimefunPlugin.instance, p, msg -> {
|
|
||||||
Config script = new Config("plugins/Slimefun/scripts/" + getAndroidType().toString() + '/' + p.getName() + ' ' + id + ".sfs");
|
|
||||||
|
|
||||||
script.setValue("author", p.getUniqueId().toString());
|
|
||||||
script.setValue("author_name", p.getName());
|
|
||||||
script.setValue("name", ChatColor.stripColor(ChatColor.translateAlternateColorCodes('&', msg)));
|
|
||||||
script.setValue("code", code);
|
|
||||||
script.setValue("downloads", 0);
|
|
||||||
script.setValue("android", getAndroidType().toString());
|
|
||||||
script.setValue("rating.positive", new ArrayList<String>());
|
|
||||||
script.setValue("rating.negative", new ArrayList<String>());
|
|
||||||
script.save();
|
|
||||||
|
|
||||||
SlimefunPlugin.getLocal().sendMessages(p, "android.scripts.uploaded");
|
|
||||||
openScriptDownloader(p, b, page);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void openScriptEditor(Player p, Block b) {
|
|
||||||
ChestMenu menu = new ChestMenu(ChatColor.DARK_AQUA + SlimefunPlugin.getLocal().getMessage(p, "android.scripts.editor"));
|
|
||||||
|
|
||||||
menu.addItem(1, new CustomItem(SlimefunUtils.getCustomHead("d9bf6db4aeda9d8822b9f736538e8c18b9a4844f84eb45504adfbfee87eb"), "&2> Edit Script", "", "&aEdits your current Script"));
|
|
||||||
menu.addMenuClickHandler(1, (pl, slot, item, action) -> {
|
|
||||||
openScript(pl, b, getScript(b.getLocation()));
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
menu.addItem(3, new CustomItem(SlimefunUtils.getCustomHead("171d8979c1878a05987a7faf21b56d1b744f9d068c74cffcde1ea1edad5852"), "&4> Create new Script", "", "&cDeletes your current Script", "&cand creates a blank one"));
|
|
||||||
menu.addMenuClickHandler(3, (pl, slot, item, action) -> {
|
|
||||||
openScript(pl, b, "START-TURN_LEFT-REPEAT");
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
menu.addItem(5, new CustomItem(SlimefunUtils.getCustomHead("c01586e39f6ffa63b4fb301b65ca7da8a92f7353aaab89d3886579125dfbaf9"), "&6> Download a Script", "", "&eDownload a Script from the Server", "&eYou can edit or simply use it"));
|
|
||||||
menu.addMenuClickHandler(5, (pl, slot, item, action) -> {
|
|
||||||
openScriptDownloader(pl, b, 1);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
menu.addItem(8, new CustomItem(SlimefunUtils.getCustomHead("a185c97dbb8353de652698d24b64327b793a3f32a98be67b719fbedab35e"), "&6> Back", "", "&7Return to the Android's interface"));
|
|
||||||
menu.addMenuClickHandler(8, (pl, slot, item, action) -> {
|
|
||||||
BlockStorage.getInventory(b).open(p);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
menu.open(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<Config> getUploadedScripts() {
|
|
||||||
List<Config> scripts = new ArrayList<>();
|
|
||||||
|
|
||||||
File directory = new File("plugins/Slimefun/scripts/" + getAndroidType().toString());
|
|
||||||
if (!directory.exists()) directory.mkdirs();
|
|
||||||
|
|
||||||
for (File script : directory.listFiles()) {
|
|
||||||
if (script.getName().endsWith("sfs")) {
|
|
||||||
scripts.add(new Config(script));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getAndroidType() != AndroidType.NONE) {
|
|
||||||
File mainDirectory = new File("plugins/Slimefun/scripts/NONE");
|
|
||||||
if (!mainDirectory.exists()) mainDirectory.mkdirs();
|
|
||||||
|
|
||||||
for (File script : mainDirectory.listFiles()) {
|
|
||||||
if (script.getName().endsWith("sfs")) {
|
|
||||||
scripts.add(new Config(script));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.sort(scripts, Comparator.comparingInt(script -> -(getScriptRating(script, true) + 1 - getScriptRating(script, false))));
|
|
||||||
|
|
||||||
return scripts;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<ScriptAction> getAccessibleScriptParts() {
|
|
||||||
List<ScriptAction> list = new ArrayList<>();
|
|
||||||
|
|
||||||
for (ScriptAction part : ScriptAction.values()) {
|
|
||||||
if (part != ScriptAction.START && part != ScriptAction.REPEAT && getAndroidType().isType(part.getRequiredType())) {
|
|
||||||
list.add(part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected float getScriptRating(Config script) {
|
|
||||||
int positive = getScriptRating(script, true) + 1;
|
|
||||||
int negative = getScriptRating(script, false);
|
|
||||||
return Math.round((positive / (double) (positive + negative)) * 100.0F) / 100.0F;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getScriptRating(Config script, boolean positive) {
|
|
||||||
if (positive) return script.getStringList("rating.positive").size();
|
|
||||||
else return script.getStringList("rating.negative").size();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getScriptRatingPercentage(Config script) {
|
|
||||||
String progress = String.valueOf(getScriptRating(script));
|
|
||||||
if (Float.parseFloat(progress) < 16.0F) progress = "&4" + progress + "&r% ";
|
|
||||||
else if (Float.parseFloat(progress) < 32.0F) progress = "&c" + progress + "&r% ";
|
|
||||||
else if (Float.parseFloat(progress) < 48.0F) progress = "&6" + progress + "&r% ";
|
|
||||||
else if (Float.parseFloat(progress) < 64.0F) progress = "&e" + progress + "&r% ";
|
|
||||||
else if (Float.parseFloat(progress) < 80.0F) progress = "&2" + progress + "&r% ";
|
|
||||||
else progress = "&a" + progress + "&r% ";
|
|
||||||
|
|
||||||
return progress;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void openScriptComponentEditor(Player p, Block b, String script, int index) {
|
|
||||||
ChestMenu menu = new ChestMenu(ChatColor.DARK_AQUA + SlimefunPlugin.getLocal().getMessage(p, "android.scripts.editor"));
|
|
||||||
String[] commands = PatternUtils.DASH.split(script);
|
|
||||||
|
|
||||||
ChestMenuUtils.drawBackground(menu, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
|
||||||
|
|
||||||
menu.addItem(9, new CustomItem(SlimefunUtils.getCustomHead("16139fd1c5654e56e9e4e2c8be7eb2bd5b499d633616663feee99b74352ad64"), "&rDo nothing"), (pl, slot, item, action) -> {
|
|
||||||
int i = 0;
|
|
||||||
StringBuilder builder = new StringBuilder("START-");
|
|
||||||
|
|
||||||
for (String command : commands) {
|
|
||||||
if (i != index && i > 0 && i < commands.length - 1) builder.append(command).append('-');
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.append("REPEAT");
|
|
||||||
setScript(b.getLocation(), builder.toString());
|
|
||||||
|
|
||||||
openScript(p, b, builder.toString());
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
int i = 10;
|
|
||||||
for (ScriptAction part : getAccessibleScriptParts()) {
|
|
||||||
menu.addItem(i, new CustomItem(part.getItem(), SlimefunPlugin.getLocal().getMessage(p, "android.scripts.instructions." + part.name())), (pl, slot, item, action) -> {
|
|
||||||
addInstruction(pl, b, index, part, commands);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
menu.open(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addInstruction(Player p, Block b, int index, ScriptAction part, String[] commands) {
|
|
||||||
int j = 0;
|
|
||||||
StringBuilder builder = new StringBuilder("START-");
|
|
||||||
|
|
||||||
for (String command : commands) {
|
|
||||||
if (j > 0) {
|
|
||||||
if (j == index) builder.append(part).append('-');
|
|
||||||
else if (j < commands.length - 1) builder.append(command).append('-');
|
|
||||||
}
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.append("REPEAT");
|
|
||||||
setScript(b.getLocation(), builder.toString());
|
|
||||||
|
|
||||||
openScript(p, b, builder.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getScript(Location l) {
|
|
||||||
return BlockStorage.getLocationInfo(l, "script");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setScript(Location l, String script) {
|
|
||||||
BlockStorage.addBlockInfo(l, "script", script);
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,6 +7,7 @@ import org.bukkit.Effect;
|
|||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.data.Ageable;
|
import org.bukkit.block.data.Ageable;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
|
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
|
||||||
@ -28,9 +29,13 @@ public abstract class FarmerAndroid extends ProgrammableAndroid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFullGrown(Block block) {
|
private boolean isFullGrown(Block block) {
|
||||||
if (!(block.getBlockData() instanceof Ageable)) return false;
|
BlockData data = block.getBlockData();
|
||||||
|
|
||||||
Ageable ageable = ((Ageable) block.getBlockData());
|
if (!(data instanceof Ageable)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ageable ageable = (Ageable) data;
|
||||||
return ageable.getAge() >= ageable.getMaximumAge();
|
return ageable.getAge() >= ageable.getMaximumAge();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +56,7 @@ public abstract class FarmerAndroid extends ProgrammableAndroid {
|
|||||||
|
|
||||||
private ItemStack getDropFromCrop(Material crop) {
|
private ItemStack getDropFromCrop(Material crop) {
|
||||||
Random random = ThreadLocalRandom.current();
|
Random random = ThreadLocalRandom.current();
|
||||||
|
|
||||||
if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14) && crop == Material.SWEET_BERRY_BUSH) {
|
if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14) && crop == Material.SWEET_BERRY_BUSH) {
|
||||||
return new ItemStack(Material.SWEET_BERRIES, random.nextInt(3) + 1);
|
return new ItemStack(Material.SWEET_BERRIES, random.nextInt(3) + 1);
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,29 @@
|
|||||||
package io.github.thebusybiscuit.slimefun4.implementation.items.androids;
|
package io.github.thebusybiscuit.slimefun4.implementation.items.androids;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.Sound;
|
||||||
import org.bukkit.Tag;
|
import org.bukkit.Tag;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.block.Dispenser;
|
import org.bukkit.block.Dispenser;
|
||||||
import org.bukkit.block.data.Rotatable;
|
import org.bukkit.block.data.Rotatable;
|
||||||
import org.bukkit.entity.Animals;
|
import org.bukkit.entity.Animals;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Monster;
|
import org.bukkit.entity.Monster;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
@ -22,6 +32,8 @@ import org.bukkit.inventory.ItemStack;
|
|||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
|
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
|
||||||
|
import io.github.thebusybiscuit.cscorelib2.chat.ChatInput;
|
||||||
|
import io.github.thebusybiscuit.cscorelib2.config.Config;
|
||||||
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
|
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
|
||||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||||
import io.github.thebusybiscuit.cscorelib2.skull.SkullBlock;
|
import io.github.thebusybiscuit.cscorelib2.skull.SkullBlock;
|
||||||
@ -30,6 +42,7 @@ import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
|
|||||||
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
|
import io.github.thebusybiscuit.slimefun4.utils.NumberUtils;
|
||||||
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
|
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
|
||||||
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
||||||
|
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
|
||||||
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu.AdvancedMenuClickHandler;
|
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu.AdvancedMenuClickHandler;
|
||||||
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction;
|
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ClickAction;
|
||||||
import me.mrCookieSlime.Slimefun.SlimefunPlugin;
|
import me.mrCookieSlime.Slimefun.SlimefunPlugin;
|
||||||
@ -41,25 +54,26 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
|
|||||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason;
|
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.UnregisterReason;
|
||||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel;
|
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineFuel;
|
||||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock;
|
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.BlockStorage;
|
||||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||||
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
|
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
|
||||||
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
|
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
|
||||||
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
|
import me.mrCookieSlime.Slimefun.api.item_transport.ItemTransportFlow;
|
||||||
|
|
||||||
public abstract class ProgrammableAndroid extends Android implements InventoryBlock, RecipeDisplayItem {
|
public abstract class ProgrammableAndroid extends SlimefunItem implements InventoryBlock, RecipeDisplayItem {
|
||||||
|
|
||||||
private static final int[] border = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 18, 24, 25, 26, 27, 33, 35, 36, 42, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 };
|
private static final List<BlockFace> POSSIBLE_ROTATIONS = Arrays.asList(BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST);
|
||||||
private static final int[] border_out = { 10, 11, 12, 13, 14, 19, 23, 28, 32, 37, 38, 39, 40, 41 };
|
private static final int[] BORDER = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 18, 24, 25, 26, 27, 33, 35, 36, 42, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 };
|
||||||
|
private static final int[] OUTPUT_BORDER = { 10, 11, 12, 13, 14, 19, 23, 28, 32, 37, 38, 39, 40, 41 };
|
||||||
|
|
||||||
protected final List<BlockFace> directions = Arrays.asList(BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST);
|
protected final Set<MachineFuel> fuelTypes = new HashSet<>();
|
||||||
protected final Set<MachineFuel> recipes = new HashSet<>();
|
|
||||||
protected final String texture;
|
protected final String texture;
|
||||||
|
|
||||||
public ProgrammableAndroid(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
public ProgrammableAndroid(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||||
super(category, item, recipeType, recipe);
|
super(category, item, recipeType, recipe);
|
||||||
|
|
||||||
this.texture = item.getSkullTexture().orElse(null);
|
texture = item.getSkullTexture().orElse(null);
|
||||||
registerDefaultFuelTypes();
|
registerDefaultFuelTypes();
|
||||||
|
|
||||||
new BlockMenuPreset(getID(), "Programmable Android") {
|
new BlockMenuPreset(getID(), "Programmable Android") {
|
||||||
@ -156,34 +170,451 @@ public abstract class ProgrammableAndroid extends Android implements InventoryBl
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This returns the {@link AndroidType} that is associated with this {@link ProgrammableAndroid}.
|
||||||
|
*
|
||||||
|
* @return The type of this {@link ProgrammableAndroid}
|
||||||
|
*/
|
||||||
|
public abstract AndroidType getAndroidType();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void preRegister() {
|
||||||
|
super.preRegister();
|
||||||
|
|
||||||
|
addItemHandler(new BlockTicker() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick(Block b, SlimefunItem item, me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config data) {
|
||||||
|
if (b != null) {
|
||||||
|
ProgrammableAndroid.this.tick(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSynchronized() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openScript(Player p, Block b, String script) {
|
||||||
|
ChestMenu menu = new ChestMenu(ChatColor.DARK_AQUA + SlimefunPlugin.getLocal().getMessage(p, "android.scripts.editor"));
|
||||||
|
|
||||||
|
menu.addItem(0, new CustomItem(ScriptAction.START.getItem(), SlimefunPlugin.getLocal().getMessage(p, "android.scripts.instructions.START"), "", "&7\u21E8 &eLeft Click &7to return to the Android's interface"));
|
||||||
|
menu.addMenuClickHandler(0, (pl, slot, item, action) -> {
|
||||||
|
BlockStorage.getInventory(b).open(pl);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
String[] commands = PatternUtils.DASH.split(script);
|
||||||
|
|
||||||
|
for (int i = 1; i < commands.length; i++) {
|
||||||
|
int index = i;
|
||||||
|
|
||||||
|
if (i == commands.length - 1) {
|
||||||
|
int additional = commands.length == 54 ? 0 : 1;
|
||||||
|
|
||||||
|
if (additional == 1) {
|
||||||
|
menu.addItem(i, new CustomItem(SlimefunUtils.getCustomHead("171d8979c1878a05987a7faf21b56d1b744f9d068c74cffcde1ea1edad5852"), "&7> Add new Command"));
|
||||||
|
menu.addMenuClickHandler(i, (pl, slot, item, action) -> {
|
||||||
|
openScriptComponentEditor(pl, b, script, index);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.addItem(i + additional, new CustomItem(ScriptAction.REPEAT.getItem(), SlimefunPlugin.getLocal().getMessage(p, "android.scripts.instructions.REPEAT"), "", "&7\u21E8 &eLeft Click &7to return to the Android's interface"));
|
||||||
|
menu.addMenuClickHandler(i + additional, (pl, slot, item, action) -> {
|
||||||
|
BlockStorage.getInventory(b).open(pl);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ItemStack stack = ScriptAction.valueOf(commands[i]).getItem();
|
||||||
|
menu.addItem(i, new CustomItem(stack, SlimefunPlugin.getLocal().getMessage(p, "android.scripts.instructions." + ScriptAction.valueOf(commands[i]).name()), "", "&7\u21E8 &eLeft Click &7to edit", "&7\u21E8 &eRight Click &7to delete", "&7\u21E8 &eShift + Right Click &7to duplicate"));
|
||||||
|
menu.addMenuClickHandler(i, (pl, slot, item, action) -> {
|
||||||
|
if (action.isRightClicked() && action.isShiftClicked()) {
|
||||||
|
if (commands.length == 54) return false;
|
||||||
|
|
||||||
|
int j = 0;
|
||||||
|
StringBuilder builder = new StringBuilder(ScriptAction.START + "-");
|
||||||
|
|
||||||
|
for (String command : commands) {
|
||||||
|
if (j > 0) {
|
||||||
|
if (j == index) {
|
||||||
|
builder.append(commands[j]).append('-').append(commands[j]).append('-');
|
||||||
|
}
|
||||||
|
else if (j < commands.length - 1) builder.append(command).append('-');
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
builder.append(ScriptAction.REPEAT);
|
||||||
|
setScript(b.getLocation(), builder.toString());
|
||||||
|
openScript(pl, b, builder.toString());
|
||||||
|
}
|
||||||
|
else if (action.isRightClicked()) {
|
||||||
|
int j = 0;
|
||||||
|
StringBuilder builder = new StringBuilder(ScriptAction.START + "-");
|
||||||
|
|
||||||
|
for (String command : commands) {
|
||||||
|
if (j != index && j > 0 && j < commands.length - 1) builder.append(command).append('-');
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append(ScriptAction.REPEAT);
|
||||||
|
setScript(b.getLocation(), builder.toString());
|
||||||
|
|
||||||
|
openScript(pl, b, builder.toString());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
openScriptComponentEditor(pl, b, script, index);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.open(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void openScriptDownloader(Player p, Block b, int page) {
|
||||||
|
ChestMenu menu = new ChestMenu("Android Scripts");
|
||||||
|
menu.addMenuOpeningHandler(pl -> pl.playSound(pl.getLocation(), Sound.BLOCK_NOTE_BLOCK_HAT, 0.7F, 0.7F));
|
||||||
|
|
||||||
|
List<Config> scripts = getUploadedScripts();
|
||||||
|
|
||||||
|
int pages = (scripts.size() / 45) + 1;
|
||||||
|
|
||||||
|
for (int i = 45; i < 54; i++) {
|
||||||
|
menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
|
||||||
|
menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.addItem(46, new CustomItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), "&r\u21E6 Previous Page", "", "&7(" + page + " / " + pages + ")"));
|
||||||
|
menu.addMenuClickHandler(46, (pl, slot, item, action) -> {
|
||||||
|
int next = page - 1;
|
||||||
|
if (next < 1) next = pages;
|
||||||
|
if (next != page) {
|
||||||
|
openScriptDownloader(pl, b, next);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.addItem(48, new CustomItem(SlimefunUtils.getCustomHead("105a2cab8b68ea57e3af992a36e47c8ff9aa87cc8776281966f8c3cf31a38"), "&eUpload a Script", "", "&6Click &7to upload your Android's Script", "&7to the Database"));
|
||||||
|
menu.addMenuClickHandler(48, (pl, slot, item, action) -> {
|
||||||
|
uploadScript(pl, b, page);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.addItem(50, new CustomItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), "&rNext Page \u21E8", "", "&7(" + page + " / " + pages + ")"));
|
||||||
|
menu.addMenuClickHandler(50, (pl, slot, item, action) -> {
|
||||||
|
int next = page + 1;
|
||||||
|
if (next > pages) next = 1;
|
||||||
|
if (next != page) {
|
||||||
|
openScriptDownloader(pl, b, next);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.addItem(53, new CustomItem(SlimefunUtils.getCustomHead("185c97dbb8353de652698d24b64327b793a3f32a98be67b719fbedab35e"), "&6> Back", "", "&7Return to the Android's interface"));
|
||||||
|
menu.addMenuClickHandler(53, (pl, slot, item, action) -> {
|
||||||
|
openScriptEditor(pl, b);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
int categoryIndex = 45 * (page - 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < 45; i++) {
|
||||||
|
int target = categoryIndex + i;
|
||||||
|
|
||||||
|
if (target >= scripts.size()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Config script = scripts.get(target);
|
||||||
|
|
||||||
|
OfflinePlayer op = Bukkit.getOfflinePlayer(script.getUUID("author"));
|
||||||
|
String author = (op != null && op.getName() != null) ? op.getName() : script.getString("author_name");
|
||||||
|
|
||||||
|
if (script.getString("author").equals(p.getUniqueId().toString())) {
|
||||||
|
menu.addItem(index, new CustomItem(this.getItem(), "&b" + script.getString("name"), "&7by &r" + author, "", "&7Downloads: &r" + script.getInt("downloads"), "&7Rating: " + getScriptRatingPercentage(script), "&a" + getScriptRating(script, true) + " \u263A &7| &4\u2639 " + getScriptRating(script, false), "", "&eLeft Click &rto download this Script", "&4(This will override your current Script)"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
menu.addItem(index, new CustomItem(this.getItem(), "&b" + script.getString("name"), "&7by &r" + author, "", "&7Downloads: &r" + script.getInt("downloads"), "&7Rating: " + getScriptRatingPercentage(script), "&a" + getScriptRating(script, true) + " \u263A &7| &4\u2639 " + getScriptRating(script, false), "", "&eLeft Click &rto download this Script", "&4(This will override your current Script)", "&eShift + Left Click &rto leave a positive Rating", "&eShift + Right Click &rto leave a negative Rating"));
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.addMenuClickHandler(index, (pl, slot, item, action) -> {
|
||||||
|
Config script2 = new Config(script.getFile());
|
||||||
|
|
||||||
|
if (action.isShiftClicked()) {
|
||||||
|
if (script2.getString("author").equals(pl.getUniqueId().toString())) {
|
||||||
|
SlimefunPlugin.getLocal().sendMessage(pl, "android.scripts.rating.own", true);
|
||||||
|
}
|
||||||
|
else if (action.isRightClicked()) {
|
||||||
|
if (!script2.getStringList("rating.negative").contains(pl.getUniqueId().toString()) && !script2.getStringList("rating.positive").contains(pl.getUniqueId().toString())) {
|
||||||
|
List<String> list = script2.getStringList("rating.negative");
|
||||||
|
list.add(p.getUniqueId().toString());
|
||||||
|
|
||||||
|
script2.setValue("rating.negative", list);
|
||||||
|
script2.save();
|
||||||
|
|
||||||
|
openScriptDownloader(pl, b, page);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SlimefunPlugin.getLocal().sendMessage(pl, "android.scripts.rating.already", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!script2.getStringList("rating.negative").contains(pl.getUniqueId().toString()) && !script2.getStringList("rating.positive").contains(pl.getUniqueId().toString())) {
|
||||||
|
List<String> list = script2.getStringList("rating.positive");
|
||||||
|
list.add(pl.getUniqueId().toString());
|
||||||
|
|
||||||
|
script2.setValue("rating.positive", list);
|
||||||
|
script2.save();
|
||||||
|
|
||||||
|
openScriptDownloader(pl, b, page);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SlimefunPlugin.getLocal().sendMessage(pl, "android.scripts.rating.already", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!action.isRightClicked()) {
|
||||||
|
script2.setValue("downloads", script2.getInt("downloads") + 1);
|
||||||
|
script2.save();
|
||||||
|
|
||||||
|
setScript(b.getLocation(), script2.getString("code"));
|
||||||
|
openScriptEditor(pl, b);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.open(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void uploadScript(Player p, Block b, int page) {
|
||||||
|
String code = getScript(b.getLocation());
|
||||||
|
int num = 1;
|
||||||
|
|
||||||
|
for (Config script : getUploadedScripts()) {
|
||||||
|
if (script.getString("author").equals(p.getUniqueId().toString())) {
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (script.getString("code").equals(code)) {
|
||||||
|
SlimefunPlugin.getLocal().sendMessage(p, "android.scripts.already-uploaded", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = num;
|
||||||
|
|
||||||
|
p.closeInventory();
|
||||||
|
SlimefunPlugin.getLocal().sendMessages(p, "android.scripts.enter-name");
|
||||||
|
|
||||||
|
ChatInput.waitForPlayer(SlimefunPlugin.instance, p, msg -> {
|
||||||
|
Config script = new Config("plugins/Slimefun/scripts/" + getAndroidType().toString() + '/' + p.getName() + ' ' + id + ".sfs");
|
||||||
|
|
||||||
|
script.setValue("author", p.getUniqueId().toString());
|
||||||
|
script.setValue("author_name", p.getName());
|
||||||
|
script.setValue("name", ChatColor.stripColor(ChatColor.translateAlternateColorCodes('&', msg)));
|
||||||
|
script.setValue("code", code);
|
||||||
|
script.setValue("downloads", 0);
|
||||||
|
script.setValue("android", getAndroidType().toString());
|
||||||
|
script.setValue("rating.positive", new ArrayList<String>());
|
||||||
|
script.setValue("rating.negative", new ArrayList<String>());
|
||||||
|
script.save();
|
||||||
|
|
||||||
|
SlimefunPlugin.getLocal().sendMessages(p, "android.scripts.uploaded");
|
||||||
|
openScriptDownloader(p, b, page);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openScriptEditor(Player p, Block b) {
|
||||||
|
ChestMenu menu = new ChestMenu(ChatColor.DARK_AQUA + SlimefunPlugin.getLocal().getMessage(p, "android.scripts.editor"));
|
||||||
|
|
||||||
|
menu.addItem(1, new CustomItem(SlimefunUtils.getCustomHead("d9bf6db4aeda9d8822b9f736538e8c18b9a4844f84eb45504adfbfee87eb"), "&2> Edit Script", "", "&aEdits your current Script"));
|
||||||
|
menu.addMenuClickHandler(1, (pl, slot, item, action) -> {
|
||||||
|
openScript(pl, b, getScript(b.getLocation()));
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.addItem(3, new CustomItem(SlimefunUtils.getCustomHead("171d8979c1878a05987a7faf21b56d1b744f9d068c74cffcde1ea1edad5852"), "&4> Create new Script", "", "&cDeletes your current Script", "&cand creates a blank one"));
|
||||||
|
menu.addMenuClickHandler(3, (pl, slot, item, action) -> {
|
||||||
|
openScript(pl, b, "START-TURN_LEFT-REPEAT");
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.addItem(5, new CustomItem(SlimefunUtils.getCustomHead("c01586e39f6ffa63b4fb301b65ca7da8a92f7353aaab89d3886579125dfbaf9"), "&6> Download a Script", "", "&eDownload a Script from the Server", "&eYou can edit or simply use it"));
|
||||||
|
menu.addMenuClickHandler(5, (pl, slot, item, action) -> {
|
||||||
|
openScriptDownloader(pl, b, 1);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.addItem(8, new CustomItem(SlimefunUtils.getCustomHead("a185c97dbb8353de652698d24b64327b793a3f32a98be67b719fbedab35e"), "&6> Back", "", "&7Return to the Android's interface"));
|
||||||
|
menu.addMenuClickHandler(8, (pl, slot, item, action) -> {
|
||||||
|
BlockStorage.getInventory(b).open(p);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.open(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<Config> getUploadedScripts() {
|
||||||
|
List<Config> scripts = new ArrayList<>();
|
||||||
|
|
||||||
|
File directory = new File("plugins/Slimefun/scripts/" + getAndroidType().toString());
|
||||||
|
if (!directory.exists()) directory.mkdirs();
|
||||||
|
|
||||||
|
for (File script : directory.listFiles()) {
|
||||||
|
if (script.getName().endsWith("sfs")) {
|
||||||
|
scripts.add(new Config(script));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getAndroidType() != AndroidType.NONE) {
|
||||||
|
File mainDirectory = new File("plugins/Slimefun/scripts/NONE");
|
||||||
|
if (!mainDirectory.exists()) mainDirectory.mkdirs();
|
||||||
|
|
||||||
|
for (File script : mainDirectory.listFiles()) {
|
||||||
|
if (script.getName().endsWith("sfs")) {
|
||||||
|
scripts.add(new Config(script));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(scripts, Comparator.comparingInt(script -> -(getScriptRating(script, true) + 1 - getScriptRating(script, false))));
|
||||||
|
|
||||||
|
return scripts;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<ScriptAction> getAccessibleScriptParts() {
|
||||||
|
List<ScriptAction> list = new ArrayList<>();
|
||||||
|
|
||||||
|
for (ScriptAction part : ScriptAction.values()) {
|
||||||
|
if (part != ScriptAction.START && part != ScriptAction.REPEAT && getAndroidType().isType(part.getRequiredType())) {
|
||||||
|
list.add(part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected float getScriptRating(Config script) {
|
||||||
|
int positive = getScriptRating(script, true) + 1;
|
||||||
|
int negative = getScriptRating(script, false);
|
||||||
|
return Math.round((positive / (double) (positive + negative)) * 100.0F) / 100.0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getScriptRating(Config script, boolean positive) {
|
||||||
|
if (positive) return script.getStringList("rating.positive").size();
|
||||||
|
else return script.getStringList("rating.negative").size();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getScriptRatingPercentage(Config script) {
|
||||||
|
String progress = String.valueOf(getScriptRating(script));
|
||||||
|
if (Float.parseFloat(progress) < 16.0F) progress = "&4" + progress + "&r% ";
|
||||||
|
else if (Float.parseFloat(progress) < 32.0F) progress = "&c" + progress + "&r% ";
|
||||||
|
else if (Float.parseFloat(progress) < 48.0F) progress = "&6" + progress + "&r% ";
|
||||||
|
else if (Float.parseFloat(progress) < 64.0F) progress = "&e" + progress + "&r% ";
|
||||||
|
else if (Float.parseFloat(progress) < 80.0F) progress = "&2" + progress + "&r% ";
|
||||||
|
else progress = "&a" + progress + "&r% ";
|
||||||
|
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void openScriptComponentEditor(Player p, Block b, String script, int index) {
|
||||||
|
ChestMenu menu = new ChestMenu(ChatColor.DARK_AQUA + SlimefunPlugin.getLocal().getMessage(p, "android.scripts.editor"));
|
||||||
|
String[] commands = PatternUtils.DASH.split(script);
|
||||||
|
|
||||||
|
ChestMenuUtils.drawBackground(menu, 0, 1, 2, 3, 4, 5, 6, 7, 8);
|
||||||
|
|
||||||
|
menu.addItem(9, new CustomItem(SlimefunUtils.getCustomHead("16139fd1c5654e56e9e4e2c8be7eb2bd5b499d633616663feee99b74352ad64"), "&rDo nothing"), (pl, slot, item, action) -> {
|
||||||
|
int i = 0;
|
||||||
|
StringBuilder builder = new StringBuilder("START-");
|
||||||
|
|
||||||
|
for (String command : commands) {
|
||||||
|
if (i != index && i > 0 && i < commands.length - 1) builder.append(command).append('-');
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append("REPEAT");
|
||||||
|
setScript(b.getLocation(), builder.toString());
|
||||||
|
|
||||||
|
openScript(p, b, builder.toString());
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
int i = 10;
|
||||||
|
for (ScriptAction part : getAccessibleScriptParts()) {
|
||||||
|
menu.addItem(i, new CustomItem(part.getItem(), SlimefunPlugin.getLocal().getMessage(p, "android.scripts.instructions." + part.name())), (pl, slot, item, action) -> {
|
||||||
|
addInstruction(pl, b, index, part, commands);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.open(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addInstruction(Player p, Block b, int index, ScriptAction part, String[] commands) {
|
||||||
|
int j = 0;
|
||||||
|
StringBuilder builder = new StringBuilder("START-");
|
||||||
|
|
||||||
|
for (String command : commands) {
|
||||||
|
if (j > 0) {
|
||||||
|
if (j == index) builder.append(part).append('-');
|
||||||
|
else if (j < commands.length - 1) builder.append(command).append('-');
|
||||||
|
}
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append("REPEAT");
|
||||||
|
setScript(b.getLocation(), builder.toString());
|
||||||
|
|
||||||
|
openScript(p, b, builder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getScript(Location l) {
|
||||||
|
return BlockStorage.getLocationInfo(l, "script");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setScript(Location l, String script) {
|
||||||
|
BlockStorage.addBlockInfo(l, "script", script);
|
||||||
|
}
|
||||||
|
|
||||||
private void registerDefaultFuelTypes() {
|
private void registerDefaultFuelTypes() {
|
||||||
if (getTier() == 1) {
|
if (getTier() == 1) {
|
||||||
registerFuel(new MachineFuel(800, new ItemStack(Material.COAL_BLOCK)));
|
registerFuelType(new MachineFuel(800, new ItemStack(Material.COAL_BLOCK)));
|
||||||
registerFuel(new MachineFuel(45, new ItemStack(Material.BLAZE_ROD)));
|
registerFuelType(new MachineFuel(45, new ItemStack(Material.BLAZE_ROD)));
|
||||||
|
|
||||||
// Coal & Charcoal
|
// Coal & Charcoal
|
||||||
registerFuel(new MachineFuel(8, new ItemStack(Material.COAL)));
|
registerFuelType(new MachineFuel(8, new ItemStack(Material.COAL)));
|
||||||
registerFuel(new MachineFuel(8, new ItemStack(Material.CHARCOAL)));
|
registerFuelType(new MachineFuel(8, new ItemStack(Material.CHARCOAL)));
|
||||||
|
|
||||||
// Logs
|
// Logs
|
||||||
for (Material mat : Tag.LOGS.getValues()) {
|
for (Material mat : Tag.LOGS.getValues()) {
|
||||||
registerFuel(new MachineFuel(2, new ItemStack(mat)));
|
registerFuelType(new MachineFuel(2, new ItemStack(mat)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wooden Planks
|
// Wooden Planks
|
||||||
for (Material mat : Tag.PLANKS.getValues()) {
|
for (Material mat : Tag.PLANKS.getValues()) {
|
||||||
registerFuel(new MachineFuel(1, new ItemStack(mat)));
|
registerFuelType(new MachineFuel(1, new ItemStack(mat)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (getTier() == 2) {
|
else if (getTier() == 2) {
|
||||||
registerFuel(new MachineFuel(100, new ItemStack(Material.LAVA_BUCKET)));
|
registerFuelType(new MachineFuel(100, new ItemStack(Material.LAVA_BUCKET)));
|
||||||
registerFuel(new MachineFuel(200, SlimefunItems.BUCKET_OF_OIL));
|
registerFuelType(new MachineFuel(200, SlimefunItems.BUCKET_OF_OIL));
|
||||||
registerFuel(new MachineFuel(500, SlimefunItems.BUCKET_OF_FUEL));
|
registerFuelType(new MachineFuel(500, SlimefunItems.BUCKET_OF_FUEL));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
registerFuel(new MachineFuel(2500, SlimefunItems.URANIUM));
|
registerFuelType(new MachineFuel(2500, SlimefunItems.URANIUM));
|
||||||
registerFuel(new MachineFuel(1200, SlimefunItems.NEPTUNIUM));
|
registerFuelType(new MachineFuel(1200, SlimefunItems.NEPTUNIUM));
|
||||||
registerFuel(new MachineFuel(3000, SlimefunItems.BOOSTED_URANIUM));
|
registerFuelType(new MachineFuel(3000, SlimefunItems.BOOSTED_URANIUM));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +627,7 @@ public abstract class ProgrammableAndroid extends Android implements InventoryBl
|
|||||||
public List<ItemStack> getDisplayRecipes() {
|
public List<ItemStack> getDisplayRecipes() {
|
||||||
List<ItemStack> list = new ArrayList<>();
|
List<ItemStack> list = new ArrayList<>();
|
||||||
|
|
||||||
for (MachineFuel fuel : recipes) {
|
for (MachineFuel fuel : fuelTypes) {
|
||||||
ItemStack item = fuel.getInput().clone();
|
ItemStack item = fuel.getInput().clone();
|
||||||
ItemMeta im = item.getItemMeta();
|
ItemMeta im = item.getItemMeta();
|
||||||
List<String> lore = new ArrayList<>();
|
List<String> lore = new ArrayList<>();
|
||||||
@ -219,8 +650,6 @@ public abstract class ProgrammableAndroid extends Android implements InventoryBl
|
|||||||
return new int[] { 20, 21, 22, 29, 30, 31 };
|
return new int[] { 20, 21, 22, 29, 30, 31 };
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract AndroidType getAndroidType();
|
|
||||||
|
|
||||||
public abstract float getFuelEfficiency();
|
public abstract float getFuelEfficiency();
|
||||||
|
|
||||||
public abstract int getTier();
|
public abstract int getTier();
|
||||||
@ -266,23 +695,23 @@ public abstract class ProgrammableAndroid extends Android implements InventoryBl
|
|||||||
BlockStorage.addBlockInfo(b, "index", String.valueOf(0));
|
BlockStorage.addBlockInfo(b, "index", String.valueOf(0));
|
||||||
break;
|
break;
|
||||||
case TURN_LEFT:
|
case TURN_LEFT:
|
||||||
int indexLeft = directions.indexOf(BlockFace.valueOf(BlockStorage.getLocationInfo(b.getLocation(), "rotation"))) - 1;
|
int indexLeft = POSSIBLE_ROTATIONS.indexOf(BlockFace.valueOf(BlockStorage.getLocationInfo(b.getLocation(), "rotation"))) - 1;
|
||||||
if (indexLeft < 0) indexLeft = directions.size() - 1;
|
if (indexLeft < 0) indexLeft = POSSIBLE_ROTATIONS.size() - 1;
|
||||||
|
|
||||||
Rotatable rotatableLeft = (Rotatable) b.getBlockData();
|
Rotatable rotatableLeft = (Rotatable) b.getBlockData();
|
||||||
rotatableLeft.setRotation(directions.get(indexLeft));
|
rotatableLeft.setRotation(POSSIBLE_ROTATIONS.get(indexLeft));
|
||||||
b.setBlockData(rotatableLeft);
|
b.setBlockData(rotatableLeft);
|
||||||
BlockStorage.addBlockInfo(b, "rotation", directions.get(indexLeft).toString());
|
BlockStorage.addBlockInfo(b, "rotation", POSSIBLE_ROTATIONS.get(indexLeft).toString());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case TURN_RIGHT:
|
case TURN_RIGHT:
|
||||||
int indexRight = directions.indexOf(BlockFace.valueOf(BlockStorage.getLocationInfo(b.getLocation(), "rotation"))) + 1;
|
int indexRight = POSSIBLE_ROTATIONS.indexOf(BlockFace.valueOf(BlockStorage.getLocationInfo(b.getLocation(), "rotation"))) + 1;
|
||||||
if (indexRight == directions.size()) indexRight = 0;
|
if (indexRight == POSSIBLE_ROTATIONS.size()) indexRight = 0;
|
||||||
|
|
||||||
Rotatable rotatableRight = (Rotatable) b.getBlockData();
|
Rotatable rotatableRight = (Rotatable) b.getBlockData();
|
||||||
rotatableRight.setRotation(directions.get(indexRight));
|
rotatableRight.setRotation(POSSIBLE_ROTATIONS.get(indexRight));
|
||||||
b.setBlockData(rotatableRight);
|
b.setBlockData(rotatableRight);
|
||||||
BlockStorage.addBlockInfo(b, "rotation", directions.get(indexRight).toString());
|
BlockStorage.addBlockInfo(b, "rotation", POSSIBLE_ROTATIONS.get(indexRight).toString());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case DIG_FORWARD:
|
case DIG_FORWARD:
|
||||||
@ -375,7 +804,7 @@ public abstract class ProgrammableAndroid extends Android implements InventoryBl
|
|||||||
ItemStack item = menu.getItemInSlot(43);
|
ItemStack item = menu.getItemInSlot(43);
|
||||||
|
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
for (MachineFuel fuel : recipes) {
|
for (MachineFuel fuel : fuelTypes) {
|
||||||
if (fuel.test(item)) {
|
if (fuel.test(item)) {
|
||||||
menu.consumeItem(43);
|
menu.consumeItem(43);
|
||||||
|
|
||||||
@ -425,25 +854,11 @@ public abstract class ProgrammableAndroid extends Android implements InventoryBl
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void move(Block b, BlockFace face, Block block) {
|
|
||||||
if (block.getY() > 0 && block.getY() < block.getWorld().getMaxHeight() && (block.getType() == Material.AIR || block.getType() == Material.CAVE_AIR)) {
|
|
||||||
block.setType(Material.PLAYER_HEAD);
|
|
||||||
Rotatable blockData = (Rotatable) block.getBlockData();
|
|
||||||
blockData.setRotation(face.getOppositeFace());
|
|
||||||
block.setBlockData(blockData);
|
|
||||||
|
|
||||||
SkullBlock.setFromBase64(block, texture);
|
|
||||||
|
|
||||||
b.setType(Material.AIR);
|
|
||||||
BlockStorage.moveBlockInfo(b.getLocation(), block.getLocation());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void constructMenu(BlockMenuPreset preset) {
|
private void constructMenu(BlockMenuPreset preset) {
|
||||||
for (int i : border) {
|
for (int i : BORDER) {
|
||||||
preset.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "), ChestMenuUtils.getEmptyClickHandler());
|
preset.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "), ChestMenuUtils.getEmptyClickHandler());
|
||||||
}
|
}
|
||||||
for (int i : border_out) {
|
for (int i : OUTPUT_BORDER) {
|
||||||
preset.addItem(i, new CustomItem(new ItemStack(Material.ORANGE_STAINED_GLASS_PANE), " "), ChestMenuUtils.getEmptyClickHandler());
|
preset.addItem(i, new CustomItem(new ItemStack(Material.ORANGE_STAINED_GLASS_PANE), " "), ChestMenuUtils.getEmptyClickHandler());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,8 +898,50 @@ public abstract class ProgrammableAndroid extends Android implements InventoryBl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerFuel(MachineFuel fuel) {
|
public void registerFuelType(MachineFuel fuel) {
|
||||||
this.recipes.add(fuel);
|
fuelTypes.add(fuel);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void move(Block b, BlockFace face, Block block) {
|
||||||
|
if (block.getY() > 0 && block.getY() < block.getWorld().getMaxHeight() && (block.getType() == Material.AIR || block.getType() == Material.CAVE_AIR)) {
|
||||||
|
block.setType(Material.PLAYER_HEAD);
|
||||||
|
Rotatable blockData = (Rotatable) block.getBlockData();
|
||||||
|
blockData.setRotation(face.getOppositeFace());
|
||||||
|
block.setBlockData(blockData);
|
||||||
|
|
||||||
|
SkullBlock.setFromBase64(block, texture);
|
||||||
|
|
||||||
|
b.setType(Material.AIR);
|
||||||
|
BlockStorage.moveBlockInfo(b.getLocation(), block.getLocation());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void killEntities(Block b, double damage, Predicate<Entity> predicate) {
|
||||||
|
throw new UnsupportedOperationException("Non-butcher Android tried to butcher!");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void fish(Block b, BlockMenu menu) {
|
||||||
|
throw new UnsupportedOperationException("Non-fishing Android tried to fish!");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void mine(Block b, BlockMenu menu, Block block) {
|
||||||
|
throw new UnsupportedOperationException("Non-mining Android tried to mine!");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void movedig(Block b, BlockMenu menu, BlockFace face, Block block) {
|
||||||
|
throw new UnsupportedOperationException("Non-mining Android tried to mine!");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean chopTree(Block b, BlockMenu menu, BlockFace face) {
|
||||||
|
throw new UnsupportedOperationException("Non-woodcutter Android tried to chop a Tree!");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void farm(BlockMenu menu, Block block) {
|
||||||
|
throw new UnsupportedOperationException("Non-farming Android tried to farm!");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void exoticFarm(BlockMenu menu, Block block) {
|
||||||
|
throw new UnsupportedOperationException("Non-farming Android tried to farm!");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -190,68 +190,18 @@ public class WitherAssembler extends SimpleSlimefunItem<BlockTicker> implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(Block b, SlimefunItem sf, Config data) {
|
public void tick(Block b, SlimefunItem sf, Config data) {
|
||||||
if (BlockStorage.getLocationInfo(b.getLocation(), "enabled").equals("false")) return;
|
if ("false".equals(BlockStorage.getLocationInfo(b.getLocation(), "enabled"))) {
|
||||||
|
return;
|
||||||
if (lifetime % 60 == 0) {
|
}
|
||||||
if (ChargableBlock.getCharge(b) < ENERGY_CONSUMPTION) return;
|
|
||||||
|
|
||||||
int soulsand = 0;
|
|
||||||
int skulls = 0;
|
|
||||||
|
|
||||||
|
if (lifetime % 60 == 0 && ChargableBlock.getCharge(b) >= ENERGY_CONSUMPTION) {
|
||||||
BlockMenu menu = BlockStorage.getInventory(b);
|
BlockMenu menu = BlockStorage.getInventory(b);
|
||||||
|
|
||||||
for (int slot : getSoulSandSlots()) {
|
boolean soulsand = findResource(menu, Material.SOUL_SAND, 4, getSoulSandSlots());
|
||||||
if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), new ItemStack(Material.SOUL_SAND), true)) {
|
boolean skulls = findResource(menu, Material.WITHER_SKELETON_SKULL, 3, getWitherSkullSlots());
|
||||||
soulsand = soulsand + menu.getItemInSlot(slot).getAmount();
|
|
||||||
|
|
||||||
if (soulsand > 3) {
|
if (soulsand && skulls) {
|
||||||
soulsand = 4;
|
consumeResources(menu);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int slot : getWitherSkullSlots()) {
|
|
||||||
if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), new ItemStack(Material.WITHER_SKELETON_SKULL), true)) {
|
|
||||||
skulls = skulls + menu.getItemInSlot(slot).getAmount();
|
|
||||||
|
|
||||||
if (skulls > 2) {
|
|
||||||
skulls = 3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (soulsand > 3 && skulls > 2) {
|
|
||||||
for (int slot : getSoulSandSlots()) {
|
|
||||||
if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), new ItemStack(Material.SOUL_SAND), true)) {
|
|
||||||
int amount = menu.getItemInSlot(slot).getAmount();
|
|
||||||
|
|
||||||
if (amount >= soulsand) {
|
|
||||||
menu.consumeItem(slot, soulsand);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
soulsand = soulsand - amount;
|
|
||||||
menu.replaceExistingItem(slot, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int slot : getWitherSkullSlots()) {
|
|
||||||
if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), new ItemStack(Material.WITHER_SKELETON_SKULL), true)) {
|
|
||||||
int amount = menu.getItemInSlot(slot).getAmount();
|
|
||||||
|
|
||||||
if (amount >= skulls) {
|
|
||||||
menu.consumeItem(slot, skulls);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
skulls = skulls - amount;
|
|
||||||
menu.replaceExistingItem(slot, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ChargableBlock.addCharge(b, -ENERGY_CONSUMPTION);
|
ChargableBlock.addCharge(b, -ENERGY_CONSUMPTION);
|
||||||
double offset = Double.parseDouble(BlockStorage.getLocationInfo(b.getLocation(), "offset"));
|
double offset = Double.parseDouble(BlockStorage.getLocationInfo(b.getLocation(), "offset"));
|
||||||
@ -273,4 +223,55 @@ public class WitherAssembler extends SimpleSlimefunItem<BlockTicker> implements
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean findResource(BlockMenu menu, Material resource, int required, int[] slots) {
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
for (int slot : slots) {
|
||||||
|
if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), new ItemStack(resource), true)) {
|
||||||
|
found += menu.getItemInSlot(slot).getAmount();
|
||||||
|
|
||||||
|
if (found > required) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void consumeResources(BlockMenu inv) {
|
||||||
|
int soulsand = 4;
|
||||||
|
int skulls = 3;
|
||||||
|
|
||||||
|
for (int slot : getSoulSandSlots()) {
|
||||||
|
if (SlimefunUtils.isItemSimilar(inv.getItemInSlot(slot), new ItemStack(Material.SOUL_SAND), true)) {
|
||||||
|
int amount = inv.getItemInSlot(slot).getAmount();
|
||||||
|
|
||||||
|
if (amount >= soulsand) {
|
||||||
|
inv.consumeItem(slot, soulsand);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
soulsand -= amount;
|
||||||
|
inv.replaceExistingItem(slot, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int slot : getWitherSkullSlots()) {
|
||||||
|
if (SlimefunUtils.isItemSimilar(inv.getItemInSlot(slot), new ItemStack(Material.WITHER_SKELETON_SKULL), true)) {
|
||||||
|
int amount = inv.getItemInSlot(slot).getAmount();
|
||||||
|
|
||||||
|
if (amount >= skulls) {
|
||||||
|
inv.consumeItem(slot, skulls);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
skulls -= amount;
|
||||||
|
inv.replaceExistingItem(slot, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@ import org.bukkit.entity.Player;
|
|||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import io.github.thebusybiscuit.cscorelib2.inventory.InvUtils;
|
|
||||||
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
||||||
import me.mrCookieSlime.Slimefun.SlimefunPlugin;
|
import me.mrCookieSlime.Slimefun.SlimefunPlugin;
|
||||||
import me.mrCookieSlime.Slimefun.Lists.SlimefunItems;
|
import me.mrCookieSlime.Slimefun.Lists.SlimefunItems;
|
||||||
@ -45,9 +44,9 @@ public class OreWasher extends MultiBlockMachine {
|
|||||||
Dispenser disp = (Dispenser) dispBlock.getState();
|
Dispenser disp = (Dispenser) dispBlock.getState();
|
||||||
Inventory inv = disp.getInventory();
|
Inventory inv = disp.getInventory();
|
||||||
|
|
||||||
for (ItemStack current : inv.getContents()) {
|
for (ItemStack input : inv.getContents()) {
|
||||||
if (current != null) {
|
if (input != null) {
|
||||||
if (SlimefunUtils.isItemSimilar(current, SlimefunItems.SIFTED_ORE, true)) {
|
if (SlimefunUtils.isItemSimilar(input, SlimefunItems.SIFTED_ORE, true)) {
|
||||||
ItemStack output = getRandomDust();
|
ItemStack output = getRandomDust();
|
||||||
Inventory outputInv = null;
|
Inventory outputInv = null;
|
||||||
|
|
||||||
@ -62,50 +61,31 @@ public class OreWasher extends MultiBlockMachine {
|
|||||||
ItemStack dummyAdding = SlimefunItems.DEBUG_FISH;
|
ItemStack dummyAdding = SlimefunItems.DEBUG_FISH;
|
||||||
outputInv = findOutputInventory(dummyAdding, dispBlock, inv);
|
outputInv = findOutputInventory(dummyAdding, dispBlock, inv);
|
||||||
}
|
}
|
||||||
else outputInv = findOutputInventory(output, dispBlock, inv);
|
else {
|
||||||
|
outputInv = findOutputInventory(output, dispBlock, inv);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeItem(p, b, inv, outputInv, input, output, 1);
|
||||||
|
|
||||||
if (outputInv != null) {
|
if (outputInv != null) {
|
||||||
ItemStack removing = current.clone();
|
outputInv.addItem(SlimefunItems.STONE_CHUNK);
|
||||||
removing.setAmount(1);
|
|
||||||
inv.removeItem(removing);
|
|
||||||
outputInv.addItem(output);
|
|
||||||
p.getWorld().playSound(b.getLocation(), Sound.ENTITY_PLAYER_SPLASH, 1, 1);
|
|
||||||
p.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, Material.WATER);
|
|
||||||
if (InvUtils.fits(outputInv, SlimefunItems.STONE_CHUNK)) outputInv.addItem(SlimefunItems.STONE_CHUNK);
|
|
||||||
}
|
}
|
||||||
else SlimefunPlugin.getLocal().sendMessage(p, "machines.full-inventory", true);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (SlimefunUtils.isItemSimilar(current, new ItemStack(Material.SAND, 2), false)) {
|
else if (SlimefunUtils.isItemSimilar(input, new ItemStack(Material.SAND, 2), false)) {
|
||||||
ItemStack output = SlimefunItems.SALT;
|
ItemStack output = SlimefunItems.SALT;
|
||||||
Inventory outputInv = findOutputInventory(output, dispBlock, inv);
|
Inventory outputInv = findOutputInventory(output, dispBlock, inv);
|
||||||
|
|
||||||
if (outputInv != null) {
|
removeItem(p, b, inv, outputInv, input, output, 2);
|
||||||
ItemStack removing = current.clone();
|
|
||||||
removing.setAmount(2);
|
|
||||||
inv.removeItem(removing);
|
|
||||||
outputInv.addItem(output.clone());
|
|
||||||
p.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, Material.WATER);
|
|
||||||
p.getWorld().playSound(b.getLocation(), Sound.ENTITY_PLAYER_SPLASH, 1, 1);
|
|
||||||
}
|
|
||||||
else SlimefunPlugin.getLocal().sendMessage(p, "machines.full-inventory", true);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (SlimefunUtils.isItemSimilar(current, SlimefunItems.PULVERIZED_ORE, true)) {
|
else if (SlimefunUtils.isItemSimilar(input, SlimefunItems.PULVERIZED_ORE, true)) {
|
||||||
ItemStack output = SlimefunItems.PURE_ORE_CLUSTER;
|
ItemStack output = SlimefunItems.PURE_ORE_CLUSTER;
|
||||||
Inventory outputInv = findOutputInventory(output, dispBlock, inv);
|
Inventory outputInv = findOutputInventory(output, dispBlock, inv);
|
||||||
|
|
||||||
if (outputInv != null) {
|
removeItem(p, b, inv, outputInv, input, output, 1);
|
||||||
ItemStack removing = current.clone();
|
|
||||||
removing.setAmount(1);
|
|
||||||
inv.removeItem(removing);
|
|
||||||
outputInv.addItem(output.clone());
|
|
||||||
p.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, Material.WATER);
|
|
||||||
p.getWorld().playSound(b.getLocation(), Sound.ENTITY_PLAYER_SPLASH, 1, 1);
|
|
||||||
}
|
|
||||||
else SlimefunPlugin.getLocal().sendMessage(p, "machines.full-inventory", true);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -114,6 +94,21 @@ public class OreWasher extends MultiBlockMachine {
|
|||||||
SlimefunPlugin.getLocal().sendMessage(p, "machines.unknown-material", true);
|
SlimefunPlugin.getLocal().sendMessage(p, "machines.unknown-material", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void removeItem(Player p, Block b, Inventory inputInv, Inventory outputInv, ItemStack input, ItemStack output, int amount) {
|
||||||
|
if (outputInv != null) {
|
||||||
|
ItemStack removing = input.clone();
|
||||||
|
removing.setAmount(amount);
|
||||||
|
inputInv.removeItem(removing);
|
||||||
|
outputInv.addItem(output.clone());
|
||||||
|
|
||||||
|
b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, Material.WATER);
|
||||||
|
b.getWorld().playSound(b.getLocation(), Sound.ENTITY_PLAYER_SPLASH, 1, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SlimefunPlugin.getLocal().sendMessage(p, "machines.full-inventory", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This returns a random dust item from Slimefun.
|
* This returns a random dust item from Slimefun.
|
||||||
*
|
*
|
||||||
|
@ -57,19 +57,7 @@ class ExplosiveTool extends SimpleSlimefunItem<BlockBreakHandler> implements Not
|
|||||||
e.getBlock().getWorld().createExplosion(e.getBlock().getLocation(), 0.0F);
|
e.getBlock().getWorld().createExplosion(e.getBlock().getLocation(), 0.0F);
|
||||||
e.getBlock().getWorld().playSound(e.getBlock().getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 0.2F, 1F);
|
e.getBlock().getWorld().playSound(e.getBlock().getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 0.2F, 1F);
|
||||||
|
|
||||||
List<Block> blocks = new ArrayList<>();
|
List<Block> blocks = findBlocks(e.getBlock());
|
||||||
for (int x = -1; x <= 1; x++) {
|
|
||||||
for (int y = -1; y <= 1; y++) {
|
|
||||||
for (int z = -1; z <= 1; z++) {
|
|
||||||
// We can skip the center block since that will break as usual
|
|
||||||
if (x == 0 && y == 0 && z == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
blocks.add(e.getBlock().getRelative(x, y, z));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callExplosionEvent.getValue().booleanValue()) {
|
if (callExplosionEvent.getValue().booleanValue()) {
|
||||||
BlockExplodeEvent blockExplodeEvent = new BlockExplodeEvent(e.getBlock(), blocks, 0);
|
BlockExplodeEvent blockExplodeEvent = new BlockExplodeEvent(e.getBlock(), blocks, 0);
|
||||||
@ -95,6 +83,25 @@ class ExplosiveTool extends SimpleSlimefunItem<BlockBreakHandler> implements Not
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Block> findBlocks(Block b) {
|
||||||
|
List<Block> blocks = new ArrayList<>(26);
|
||||||
|
|
||||||
|
for (int x = -1; x <= 1; x++) {
|
||||||
|
for (int y = -1; y <= 1; y++) {
|
||||||
|
for (int z = -1; z <= 1; z++) {
|
||||||
|
// We can skip the center block since that will break as usual
|
||||||
|
if (x == 0 && y == 0 && z == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
blocks.add(b.getRelative(x, y, z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDamageable() {
|
public boolean isDamageable() {
|
||||||
return damageOnUse.getValue();
|
return damageOnUse.getValue();
|
||||||
|
@ -9,6 +9,8 @@ import org.bukkit.event.block.BlockBreakEvent;
|
|||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
|
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.BrokenSpawner;
|
||||||
|
import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.RepairedSpawner;
|
||||||
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
|
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
|
||||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||||
import me.mrCookieSlime.Slimefun.Lists.SlimefunItems;
|
import me.mrCookieSlime.Slimefun.Lists.SlimefunItems;
|
||||||
@ -19,6 +21,14 @@ import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
|||||||
import me.mrCookieSlime.Slimefun.api.Slimefun;
|
import me.mrCookieSlime.Slimefun.api.Slimefun;
|
||||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link PickaxeOfContainment} is a Pickaxe that allows you to break Spawners.
|
||||||
|
* Upon breaking a Spawner, a {@link BrokenSpawner} will be dropped.
|
||||||
|
* But it also allows you to break a {@link RepairedSpawner}.
|
||||||
|
*
|
||||||
|
* @author Admin
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class PickaxeOfContainment extends SimpleSlimefunItem<BlockBreakHandler> {
|
public class PickaxeOfContainment extends SimpleSlimefunItem<BlockBreakHandler> {
|
||||||
|
|
||||||
public PickaxeOfContainment(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
public PickaxeOfContainment(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||||
@ -47,25 +57,9 @@ public class PickaxeOfContainment extends SimpleSlimefunItem<BlockBreakHandler>
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the spawner's BlockStorage has BlockInfo, then it's not a vanilla spawner and
|
ItemStack spawner = breakSpawner(b);
|
||||||
// should not give a broken spawner.
|
|
||||||
ItemStack spawner = SlimefunItems.BROKEN_SPAWNER.clone();
|
|
||||||
if (BlockStorage.hasBlockInfo(b)) {
|
|
||||||
spawner = SlimefunItems.REPAIRED_SPAWNER.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemMeta im = spawner.getItemMeta();
|
|
||||||
List<String> lore = im.getLore();
|
|
||||||
|
|
||||||
for (int i = 0; i < lore.size(); i++) {
|
|
||||||
if (lore.get(i).contains("<Type>")) {
|
|
||||||
lore.set(i, lore.get(i).replace("<Type>", ChatUtils.humanize(((CreatureSpawner) b.getState()).getSpawnedType().toString())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
im.setLore(lore);
|
|
||||||
spawner.setItemMeta(im);
|
|
||||||
b.getLocation().getWorld().dropItemNaturally(b.getLocation(), spawner);
|
b.getLocation().getWorld().dropItemNaturally(b.getLocation(), spawner);
|
||||||
|
|
||||||
e.setExpToDrop(0);
|
e.setExpToDrop(0);
|
||||||
e.setDropItems(false);
|
e.setDropItems(false);
|
||||||
return true;
|
return true;
|
||||||
@ -78,4 +72,27 @@ public class PickaxeOfContainment extends SimpleSlimefunItem<BlockBreakHandler>
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ItemStack breakSpawner(Block b) {
|
||||||
|
// If the spawner's BlockStorage has BlockInfo, then it's not a vanilla spawner and
|
||||||
|
// should not give a broken spawner.
|
||||||
|
ItemStack spawner = SlimefunItems.BROKEN_SPAWNER.clone();
|
||||||
|
|
||||||
|
if (BlockStorage.hasBlockInfo(b)) {
|
||||||
|
spawner = SlimefunItems.REPAIRED_SPAWNER.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemMeta im = spawner.getItemMeta();
|
||||||
|
List<String> lore = im.getLore();
|
||||||
|
|
||||||
|
for (int i = 0; i < lore.size(); i++) {
|
||||||
|
if (lore.get(i).contains("<Type>")) {
|
||||||
|
lore.set(i, lore.get(i).replace("<Type>", ChatUtils.humanize(((CreatureSpawner) b.getState()).getSpawnedType().toString())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
im.setLore(lore);
|
||||||
|
spawner.setItemMeta(im);
|
||||||
|
return spawner;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ import java.util.List;
|
|||||||
import org.bukkit.Effect;
|
import org.bukkit.Effect;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.enchantments.Enchantment;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.block.BlockBreakEvent;
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
@ -12,17 +14,38 @@ import io.github.thebusybiscuit.cscorelib2.blocks.Vein;
|
|||||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||||
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
|
import io.github.thebusybiscuit.cscorelib2.materials.MaterialCollections;
|
||||||
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
||||||
|
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
|
||||||
import me.mrCookieSlime.Slimefun.SlimefunPlugin;
|
import me.mrCookieSlime.Slimefun.SlimefunPlugin;
|
||||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SimpleSlimefunItem;
|
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SimpleSlimefunItem;
|
||||||
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockBreakHandler;
|
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockBreakHandler;
|
||||||
|
import me.mrCookieSlime.Slimefun.api.Slimefun;
|
||||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link PickaxeOfVeinMining} is a powerful tool which allows you to mine an entire vein of ores
|
||||||
|
* at once. It even works with the fortune {@link Enchantment}.
|
||||||
|
*
|
||||||
|
* @author TheBusyBiscuit
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class PickaxeOfVeinMining extends SimpleSlimefunItem<BlockBreakHandler> {
|
public class PickaxeOfVeinMining extends SimpleSlimefunItem<BlockBreakHandler> {
|
||||||
|
|
||||||
|
private final ItemSetting<Integer> maxBlocks = new ItemSetting<Integer>("max-blocks", 16) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validateInput(Integer input) {
|
||||||
|
// We do not wanna allow any negative values here
|
||||||
|
return super.validateInput(input) && input.intValue() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
public PickaxeOfVeinMining(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
public PickaxeOfVeinMining(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||||
super(category, item, recipeType, recipe);
|
super(category, item, recipeType, recipe);
|
||||||
|
|
||||||
|
addItemSetting(maxBlocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -36,26 +59,34 @@ public class PickaxeOfVeinMining extends SimpleSlimefunItem<BlockBreakHandler> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onBlockBreak(BlockBreakEvent e, ItemStack item, int fortune, List<ItemStack> drops) {
|
public boolean onBlockBreak(BlockBreakEvent e, ItemStack item, int fortune, List<ItemStack> drops) {
|
||||||
if (MaterialCollections.getAllOres().contains(e.getBlock().getType()) && isItem(item)) {
|
if (!Slimefun.hasUnlocked(e.getPlayer(), PickaxeOfVeinMining.this, true)) {
|
||||||
List<Block> blocks = Vein.find(e.getBlock(), 16, MaterialCollections.getAllOres());
|
|
||||||
|
|
||||||
for (Block b : blocks) {
|
|
||||||
if (SlimefunPlugin.getProtectionManager().hasPermission(e.getPlayer(), b.getLocation(), ProtectableAction.BREAK_BLOCK)) {
|
|
||||||
b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getType());
|
|
||||||
|
|
||||||
for (ItemStack drop : b.getDrops(getItem())) {
|
|
||||||
b.getWorld().dropItemNaturally(b.getLocation(), drop.getType().isBlock() ? drop : new CustomItem(drop, fortune));
|
|
||||||
}
|
|
||||||
|
|
||||||
b.setType(Material.AIR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else return false;
|
|
||||||
|
if (MaterialCollections.getAllOres().contains(e.getBlock().getType()) && isItem(item)) {
|
||||||
|
List<Block> blocks = Vein.find(e.getBlock(), maxBlocks.getValue(), MaterialCollections.getAllOres());
|
||||||
|
breakBlocks(e.getPlayer(), blocks, fortune);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void breakBlocks(Player p, List<Block> blocks, int fortune) {
|
||||||
|
for (Block b : blocks) {
|
||||||
|
if (SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), ProtectableAction.BREAK_BLOCK)) {
|
||||||
|
b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getType());
|
||||||
|
|
||||||
|
for (ItemStack drop : b.getDrops(getItem())) {
|
||||||
|
b.getWorld().dropItemNaturally(b.getLocation(), drop.getType().isBlock() ? drop : new CustomItem(drop, fortune));
|
||||||
|
}
|
||||||
|
|
||||||
|
b.setType(Material.AIR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ import java.util.List;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.bukkit.Effect;
|
import org.bukkit.Effect;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.event.block.BlockBreakEvent;
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
@ -36,24 +38,21 @@ public class SmeltersPickaxe extends SimpleSlimefunItem<BlockBreakHandler> imple
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onBlockBreak(BlockBreakEvent e, ItemStack item, int fortune, List<ItemStack> drops) {
|
public boolean onBlockBreak(BlockBreakEvent e, ItemStack item, int fortune, List<ItemStack> drops) {
|
||||||
|
if (!Slimefun.hasUnlocked(e.getPlayer(), SmeltersPickaxe.this, true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (MaterialCollections.getAllOres().contains(e.getBlock().getType()) && isItem(item)) {
|
if (MaterialCollections.getAllOres().contains(e.getBlock().getType()) && isItem(item)) {
|
||||||
if (BlockStorage.hasBlockInfo(e.getBlock())) return true;
|
if (BlockStorage.hasBlockInfo(e.getBlock())) {
|
||||||
if (!Slimefun.hasUnlocked(e.getPlayer(), SmeltersPickaxe.this, true)) return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Collection<ItemStack> blockDrops = e.getBlock().getDrops(getItem());
|
Collection<ItemStack> blockDrops = e.getBlock().getDrops(getItem());
|
||||||
|
|
||||||
for (ItemStack drop : blockDrops) {
|
for (ItemStack drop : blockDrops) {
|
||||||
if (drop != null) {
|
if (drop != null && drop.getType() != Material.AIR) {
|
||||||
ItemStack output = drop;
|
smelt(e.getBlock(), drop, fortune);
|
||||||
output.setAmount(fortune);
|
drops.add(drop);
|
||||||
|
|
||||||
Optional<ItemStack> furnaceOutput = SlimefunPlugin.getMinecraftRecipes().getFurnaceOutput(drop);
|
|
||||||
if (furnaceOutput.isPresent()) {
|
|
||||||
e.getBlock().getWorld().playEffect(e.getBlock().getLocation(), Effect.MOBSPAWNER_FLAMES, 1);
|
|
||||||
output.setType(furnaceOutput.get().getType());
|
|
||||||
}
|
|
||||||
|
|
||||||
drops.add(output);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +65,16 @@ public class SmeltersPickaxe extends SimpleSlimefunItem<BlockBreakHandler> imple
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void smelt(Block b, ItemStack drop, int fortune) {
|
||||||
|
Optional<ItemStack> furnaceOutput = SlimefunPlugin.getMinecraftRecipes().getFurnaceOutput(drop);
|
||||||
|
|
||||||
|
if (furnaceOutput.isPresent()) {
|
||||||
|
b.getWorld().playEffect(b.getLocation(), Effect.MOBSPAWNER_FLAMES, 1);
|
||||||
|
drop.setType(furnaceOutput.get().getType());
|
||||||
|
drop.setAmount(fortune);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDamageable() {
|
public boolean isDamageable() {
|
||||||
return true;
|
return true;
|
||||||
|
@ -28,8 +28,20 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SimpleSlimefunItem;
|
|||||||
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemUseHandler;
|
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemUseHandler;
|
||||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link SeismicAxe} is an interesting weapon. It spawns ghostly block entities in a straight line
|
||||||
|
* when right-clicked. These blocks launch up from the ground and damage any {@link LivingEntity} in its way.
|
||||||
|
* It is quite similar to a shockwave.
|
||||||
|
*
|
||||||
|
* @author TheBusyBiscuit
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class SeismicAxe extends SimpleSlimefunItem<ItemUseHandler> implements NotPlaceable, DamageableItem {
|
public class SeismicAxe extends SimpleSlimefunItem<ItemUseHandler> implements NotPlaceable, DamageableItem {
|
||||||
|
|
||||||
|
private static final float STRENGTH = 1.2F;
|
||||||
|
private static final float DAMAGE = 6;
|
||||||
|
private static final int RANGE = 10;
|
||||||
|
|
||||||
public SeismicAxe(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
public SeismicAxe(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||||
super(category, item, recipeType, recipe);
|
super(category, item, recipeType, recipe);
|
||||||
}
|
}
|
||||||
@ -38,45 +50,25 @@ public class SeismicAxe extends SimpleSlimefunItem<ItemUseHandler> implements No
|
|||||||
public ItemUseHandler getItemHandler() {
|
public ItemUseHandler getItemHandler() {
|
||||||
return e -> {
|
return e -> {
|
||||||
Player p = e.getPlayer();
|
Player p = e.getPlayer();
|
||||||
List<Block> blocks = p.getLineOfSight(null, 10);
|
List<Block> blocks = p.getLineOfSight(null, RANGE);
|
||||||
|
|
||||||
for (int i = 0; i < blocks.size(); i++) {
|
for (int i = 2; i < blocks.size(); i++) {
|
||||||
Block b = blocks.get(i);
|
Block ground = findGround(blocks.get(i));
|
||||||
Location ground = b.getLocation();
|
Location groundLocation = ground.getLocation();
|
||||||
|
|
||||||
if (b.getType() == null || b.getType() == Material.AIR) {
|
ground.getWorld().playEffect(groundLocation, Effect.STEP_SOUND, ground.getType());
|
||||||
for (int y = ground.getBlockY(); y > 0; y--) {
|
|
||||||
if (b.getWorld().getBlockAt(b.getX(), y, b.getZ()) != null && b.getWorld().getBlockAt(b.getX(), y, b.getZ()).getType() != null && b.getWorld().getBlockAt(b.getX(), y, b.getZ()).getType() != Material.AIR) {
|
|
||||||
ground = new Location(b.getWorld(), b.getX(), y, b.getZ());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
b.getWorld().playEffect(ground, Effect.STEP_SOUND, ground.getBlock().getType());
|
if (ground.getRelative(BlockFace.UP).getType() == Material.AIR) {
|
||||||
|
Location loc = ground.getRelative(BlockFace.UP).getLocation().add(0.5, 0.0, 0.5);
|
||||||
if (ground.getBlock().getRelative(BlockFace.UP).getType() == null || ground.getBlock().getRelative(BlockFace.UP).getType() == Material.AIR) {
|
FallingBlock block = ground.getWorld().spawnFallingBlock(loc, ground.getBlockData());
|
||||||
Location loc = ground.getBlock().getRelative(BlockFace.UP).getLocation().add(0.5, 0.0, 0.5);
|
|
||||||
FallingBlock block = ground.getWorld().spawnFallingBlock(loc, ground.getBlock().getBlockData());
|
|
||||||
block.setDropItem(false);
|
block.setDropItem(false);
|
||||||
block.setVelocity(new Vector(0, 0.4 + i * 0.01, 0));
|
block.setVelocity(new Vector(0, 0.4 + i * 0.01, 0));
|
||||||
block.setMetadata("seismic_axe", new FixedMetadataValue(SlimefunPlugin.instance, "fake_block"));
|
block.setMetadata("seismic_axe", new FixedMetadataValue(SlimefunPlugin.instance, "fake_block"));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Entity n : ground.getChunk().getEntities()) {
|
for (Entity n : ground.getChunk().getEntities()) {
|
||||||
if (n instanceof LivingEntity && n.getType() != EntityType.ARMOR_STAND && n.getLocation().distance(ground) <= 2.0D && !n.getUniqueId().equals(p.getUniqueId())) {
|
if (n instanceof LivingEntity && n.getType() != EntityType.ARMOR_STAND && n.getLocation().distance(groundLocation) <= 2.0D && !n.getUniqueId().equals(p.getUniqueId())) {
|
||||||
Vector vector = n.getLocation().toVector().subtract(p.getLocation().toVector()).normalize().multiply(1.4);
|
pushEntity(p, n);
|
||||||
vector.setY(0.9);
|
|
||||||
n.setVelocity(vector);
|
|
||||||
|
|
||||||
if (n.getType() != EntityType.PLAYER || p.getWorld().getPVP()) {
|
|
||||||
EntityDamageByEntityEvent event = new EntityDamageByEntityEvent(p, n, DamageCause.ENTITY_ATTACK, 6D);
|
|
||||||
Bukkit.getPluginManager().callEvent(event);
|
|
||||||
|
|
||||||
if (!event.isCancelled()) {
|
|
||||||
((LivingEntity) n).damage(6D);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,6 +79,36 @@ public class SeismicAxe extends SimpleSlimefunItem<ItemUseHandler> implements No
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void pushEntity(Player p, Entity entity) {
|
||||||
|
Vector vector = entity.getLocation().toVector().subtract(p.getLocation().toVector()).normalize();
|
||||||
|
vector.multiply(STRENGTH);
|
||||||
|
vector.setY(0.9);
|
||||||
|
entity.setVelocity(vector);
|
||||||
|
|
||||||
|
if (entity.getType() != EntityType.PLAYER || p.getWorld().getPVP()) {
|
||||||
|
EntityDamageByEntityEvent event = new EntityDamageByEntityEvent(p, entity, DamageCause.ENTITY_ATTACK, 6D);
|
||||||
|
Bukkit.getPluginManager().callEvent(event);
|
||||||
|
|
||||||
|
if (!event.isCancelled()) {
|
||||||
|
((LivingEntity) entity).damage(DAMAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Block findGround(Block b) {
|
||||||
|
if (b.getType() == Material.AIR) {
|
||||||
|
for (int y = 0; y < b.getY(); y++) {
|
||||||
|
Block block = b.getRelative(0, -y, 0);
|
||||||
|
|
||||||
|
if (block.getType() != Material.AIR) {
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDamageable() {
|
public boolean isDamageable() {
|
||||||
return true;
|
return true;
|
||||||
|
@ -35,6 +35,7 @@ public class SeismicAxeListener implements Listener {
|
|||||||
|
|
||||||
if (e.getEntity().getType() == EntityType.FALLING_BLOCK && e.getEntity().hasMetadata("seismic_axe")) {
|
if (e.getEntity().getType() == EntityType.FALLING_BLOCK && e.getEntity().hasMetadata("seismic_axe")) {
|
||||||
e.setCancelled(true);
|
e.setCancelled(true);
|
||||||
|
e.getEntity().removeMetadata("seismic_axe", SlimefunPlugin.instance);
|
||||||
e.getEntity().remove();
|
e.getEntity().remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,32 +199,16 @@ public final class PostSetup {
|
|||||||
Smeltery smeltery = (Smeltery) SlimefunItems.SMELTERY.getItem();
|
Smeltery smeltery = (Smeltery) SlimefunItems.SMELTERY.getItem();
|
||||||
|
|
||||||
if (smeltery != null && !smeltery.isDisabled()) {
|
if (smeltery != null && !smeltery.isDisabled()) {
|
||||||
|
MakeshiftSmeltery makeshiftSmeltery = ((MakeshiftSmeltery) SlimefunItems.MAKESHIFT_SMELTERY.getItem());
|
||||||
ItemStack[] input = null;
|
ItemStack[] input = null;
|
||||||
|
|
||||||
for (ItemStack[] recipe : smeltery.getRecipes()) {
|
for (ItemStack[] output : smeltery.getRecipes()) {
|
||||||
if (input == null) {
|
if (input == null) {
|
||||||
input = recipe;
|
input = output;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (input[0] != null && recipe[0] != null) {
|
if (input[0] != null && output[0] != null) {
|
||||||
List<ItemStack> inputs = new ArrayList<>();
|
addSmelteryRecipe(input, output, makeshiftSmeltery);
|
||||||
|
|
||||||
for (ItemStack item : input) {
|
|
||||||
if (item != null) {
|
|
||||||
inputs.add(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We want to exclude Dust to Ingot Recipes
|
|
||||||
if (inputs.size() == 1 && isDust(inputs.get(0))) {
|
|
||||||
((MakeshiftSmeltery) SlimefunItems.MAKESHIFT_SMELTERY.getItem()).addRecipe(new ItemStack[] { inputs.get(0) }, recipe[0]);
|
|
||||||
|
|
||||||
registerMachineRecipe("ELECTRIC_INGOT_FACTORY", 8, new ItemStack[] { inputs.get(0) }, new ItemStack[] { recipe[0] });
|
|
||||||
registerMachineRecipe("ELECTRIC_INGOT_PULVERIZER", 3, new ItemStack[] { recipe[0] }, new ItemStack[] { inputs.get(0) });
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
registerMachineRecipe("ELECTRIC_SMELTERY", 12, inputs.toArray(new ItemStack[0]), new ItemStack[] { recipe[0] });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input = null;
|
input = null;
|
||||||
@ -240,6 +224,28 @@ public final class PostSetup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void addSmelteryRecipe(ItemStack[] input, ItemStack[] output, MakeshiftSmeltery makeshiftSmeltery) {
|
||||||
|
List<ItemStack> ingredients = new ArrayList<>();
|
||||||
|
|
||||||
|
// Filter out 'null' items
|
||||||
|
for (ItemStack item : input) {
|
||||||
|
if (item != null) {
|
||||||
|
ingredients.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We want to redirect Dust to Ingot Recipes
|
||||||
|
if (ingredients.size() == 1 && isDust(ingredients.get(0))) {
|
||||||
|
makeshiftSmeltery.addRecipe(new ItemStack[] { ingredients.get(0) }, output[0]);
|
||||||
|
|
||||||
|
registerMachineRecipe("ELECTRIC_INGOT_FACTORY", 8, new ItemStack[] { ingredients.get(0) }, new ItemStack[] { output[0] });
|
||||||
|
registerMachineRecipe("ELECTRIC_INGOT_PULVERIZER", 3, new ItemStack[] { output[0] }, new ItemStack[] { ingredients.get(0) });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
registerMachineRecipe("ELECTRIC_SMELTERY", 12, ingredients.toArray(new ItemStack[0]), new ItemStack[] { output[0] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean isDust(ItemStack item) {
|
private static boolean isDust(ItemStack item) {
|
||||||
SlimefunItem sfItem = SlimefunItem.getByItem(item);
|
SlimefunItem sfItem = SlimefunItem.getByItem(item);
|
||||||
return sfItem != null && sfItem.getID().endsWith("_DUST");
|
return sfItem != null && sfItem.getID().endsWith("_DUST");
|
||||||
|
@ -19,6 +19,8 @@ import org.bukkit.inventory.meta.ItemMeta;
|
|||||||
*/
|
*/
|
||||||
public final class ItemStackWrapper extends ItemStack {
|
public final class ItemStackWrapper extends ItemStack {
|
||||||
|
|
||||||
|
private static final String ERROR_MESSAGE = "ItemStackWrappers are immutable and not indended for actual usage.";
|
||||||
|
|
||||||
private final ItemMeta meta;
|
private final ItemMeta meta;
|
||||||
private final boolean hasItemMeta;
|
private final boolean hasItemMeta;
|
||||||
|
|
||||||
@ -49,37 +51,37 @@ public final class ItemStackWrapper extends ItemStack {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
throw new UnsupportedOperationException("ItemStackWrappers do not allow .equals()");
|
throw new UnsupportedOperationException(ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
throw new UnsupportedOperationException("You cannot hash an ItemStackWrapper");
|
throw new UnsupportedOperationException(ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack clone() {
|
public ItemStack clone() {
|
||||||
throw new UnsupportedOperationException("You cannot clone an ItemStackWrapper");
|
throw new UnsupportedOperationException(ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setType(Material type) {
|
public void setType(Material type) {
|
||||||
throw new UnsupportedOperationException("ItemStackWrappers are immutable and not indended for actual usage.");
|
throw new UnsupportedOperationException(ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAmount(int amount) {
|
public void setAmount(int amount) {
|
||||||
throw new UnsupportedOperationException("ItemStackWrappers are immutable and not indended for actual usage.");
|
throw new UnsupportedOperationException(ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setItemMeta(ItemMeta itemMeta) {
|
public boolean setItemMeta(ItemMeta itemMeta) {
|
||||||
throw new UnsupportedOperationException("ItemStackWrappers are immutable and not indended for actual usage.");
|
throw new UnsupportedOperationException(ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addUnsafeEnchantment(Enchantment ench, int level) {
|
public void addUnsafeEnchantment(Enchantment ench, int level) {
|
||||||
throw new UnsupportedOperationException("ItemStackWrappers are immutable and not indended for actual usage.");
|
throw new UnsupportedOperationException(ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user