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 Cocoa Organic Food
|
||||
* Added Cocoa Fertilizer
|
||||
* Added a configurable limit to the Pickaxe of Vein Mining
|
||||
|
||||
#### Changes
|
||||
* Fixed a few memory leaks
|
||||
@ -36,6 +37,7 @@
|
||||
* Dried Kelp Blocks can now be used in the Coal Generator
|
||||
* Crafting Organic Food/Fertilizer yields more output now
|
||||
* 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
|
||||
* Fixed Ore Washer recipes showing up twice
|
||||
|
@ -47,6 +47,26 @@ class GiveCommand extends SubCommand {
|
||||
SlimefunItem sfItem = SlimefunItem.getByID(args[2].toUpperCase(Locale.ROOT));
|
||||
|
||||
if (sfItem != null) {
|
||||
giveItem(sender, p, sfItem, args);
|
||||
}
|
||||
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.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");
|
||||
}
|
||||
@ -63,14 +83,6 @@ class GiveCommand extends SubCommand {
|
||||
}
|
||||
}
|
||||
}
|
||||
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.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) {
|
||||
int amount = 1;
|
||||
|
@ -35,8 +35,12 @@ class GitHubIssuesTracker extends GitHubConnector {
|
||||
for (JsonElement elem : array) {
|
||||
JsonObject obj = elem.getAsJsonObject();
|
||||
|
||||
if (obj.has("pull_request")) pullRequests++;
|
||||
else issues++;
|
||||
if (obj.has("pull_request")) {
|
||||
pullRequests++;
|
||||
}
|
||||
else {
|
||||
issues++;
|
||||
}
|
||||
}
|
||||
|
||||
callback.update(issues, pullRequests);
|
||||
|
@ -45,22 +45,42 @@ class GitHubTask implements Runnable {
|
||||
// Store all queried usernames to prevent 429 responses for pinging the
|
||||
// same URL twice in one run.
|
||||
Map<String, String> skins = new HashMap<>();
|
||||
int count = 0;
|
||||
int requests = 0;
|
||||
|
||||
for (Contributor contributor : gitHubService.getContributors().values()) {
|
||||
int newRequests = requestTexture(contributor, skins);
|
||||
requests += newRequests;
|
||||
|
||||
if (newRequests < 0 || requests >= MAX_REQUESTS_PER_MINUTE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (requests >= MAX_REQUESTS_PER_MINUTE) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
for (GitHubConnector connector : gitHubService.getConnectors()) {
|
||||
if (connector instanceof ContributionsConnector && !((ContributionsConnector) connector).hasFinished()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We only wanna save this if all Connectors finished already
|
||||
// This will run multiple times but thats okay, this way we get as much data as possible stored
|
||||
gitHubService.saveUUIDCache();
|
||||
}
|
||||
|
||||
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(grabTexture(skins, contributor));
|
||||
|
||||
count += contributor.getUniqueId().isPresent() ? 1 : 2;
|
||||
|
||||
if (count >= MAX_REQUESTS_PER_MINUTE) {
|
||||
break;
|
||||
}
|
||||
contributor.setTexture(pullTexture(skins, contributor));
|
||||
return contributor.getUniqueId().isPresent() ? 1 : 2;
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException x) {
|
||||
@ -77,36 +97,20 @@ class GitHubTask implements Runnable {
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(SlimefunPlugin.instance, this::grabTextures, 5 * 60 * 20L);
|
||||
}
|
||||
|
||||
count = 0;
|
||||
break;
|
||||
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);
|
||||
|
||||
count = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count >= MAX_REQUESTS_PER_MINUTE) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
for (GitHubConnector connector : gitHubService.getConnectors()) {
|
||||
if (connector instanceof ContributionsConnector && !((ContributionsConnector) connector).hasFinished()) {
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// We only wanna save this if all Connectors finished already
|
||||
// This will run multiple times but thats okay, this way we get as much data as possible stored
|
||||
gitHubService.saveUUIDCache();
|
||||
return 0;
|
||||
}
|
||||
|
||||
private String grabTexture(Map<String, String> skins, Contributor contributor) throws TooManyRequestsException, IOException {
|
||||
private String pullTexture(Map<String, String> skins, Contributor contributor) throws TooManyRequestsException, IOException {
|
||||
Optional<UUID> uuid = contributor.getUniqueId();
|
||||
|
||||
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.block.Block;
|
||||
import org.bukkit.block.data.Ageable;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
|
||||
@ -28,9 +29,13 @@ public abstract class FarmerAndroid extends ProgrammableAndroid {
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -1,19 +1,29 @@
|
||||
package io.github.thebusybiscuit.slimefun4.implementation.items.androids;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
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.OfflinePlayer;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.Tag;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.Dispenser;
|
||||
import org.bukkit.block.data.Rotatable;
|
||||
import org.bukkit.entity.Animals;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Monster;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
@ -22,6 +32,8 @@ import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.chat.ChatColors;
|
||||
import io.github.thebusybiscuit.cscorelib2.chat.ChatInput;
|
||||
import io.github.thebusybiscuit.cscorelib2.config.Config;
|
||||
import io.github.thebusybiscuit.cscorelib2.inventory.ItemUtils;
|
||||
import io.github.thebusybiscuit.cscorelib2.item.CustomItem;
|
||||
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.PatternUtils;
|
||||
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.ClickAction;
|
||||
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.abstractItems.MachineFuel;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.interfaces.InventoryBlock;
|
||||
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;
|
||||
import me.mrCookieSlime.Slimefun.api.BlockStorage;
|
||||
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
|
||||
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
|
||||
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenuPreset;
|
||||
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 int[] border_out = { 10, 11, 12, 13, 14, 19, 23, 28, 32, 37, 38, 39, 40, 41 };
|
||||
private static final List<BlockFace> POSSIBLE_ROTATIONS = Arrays.asList(BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST);
|
||||
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> recipes = new HashSet<>();
|
||||
protected final Set<MachineFuel> fuelTypes = new HashSet<>();
|
||||
protected final String texture;
|
||||
|
||||
public ProgrammableAndroid(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
super(category, item, recipeType, recipe);
|
||||
|
||||
this.texture = item.getSkullTexture().orElse(null);
|
||||
texture = item.getSkullTexture().orElse(null);
|
||||
registerDefaultFuelTypes();
|
||||
|
||||
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() {
|
||||
if (getTier() == 1) {
|
||||
registerFuel(new MachineFuel(800, new ItemStack(Material.COAL_BLOCK)));
|
||||
registerFuel(new MachineFuel(45, new ItemStack(Material.BLAZE_ROD)));
|
||||
registerFuelType(new MachineFuel(800, new ItemStack(Material.COAL_BLOCK)));
|
||||
registerFuelType(new MachineFuel(45, new ItemStack(Material.BLAZE_ROD)));
|
||||
|
||||
// Coal & Charcoal
|
||||
registerFuel(new MachineFuel(8, new ItemStack(Material.COAL)));
|
||||
registerFuel(new MachineFuel(8, new ItemStack(Material.CHARCOAL)));
|
||||
registerFuelType(new MachineFuel(8, new ItemStack(Material.COAL)));
|
||||
registerFuelType(new MachineFuel(8, new ItemStack(Material.CHARCOAL)));
|
||||
|
||||
// Logs
|
||||
for (Material mat : Tag.LOGS.getValues()) {
|
||||
registerFuel(new MachineFuel(2, new ItemStack(mat)));
|
||||
registerFuelType(new MachineFuel(2, new ItemStack(mat)));
|
||||
}
|
||||
|
||||
// Wooden Planks
|
||||
for (Material mat : Tag.PLANKS.getValues()) {
|
||||
registerFuel(new MachineFuel(1, new ItemStack(mat)));
|
||||
registerFuelType(new MachineFuel(1, new ItemStack(mat)));
|
||||
}
|
||||
}
|
||||
else if (getTier() == 2) {
|
||||
registerFuel(new MachineFuel(100, new ItemStack(Material.LAVA_BUCKET)));
|
||||
registerFuel(new MachineFuel(200, SlimefunItems.BUCKET_OF_OIL));
|
||||
registerFuel(new MachineFuel(500, SlimefunItems.BUCKET_OF_FUEL));
|
||||
registerFuelType(new MachineFuel(100, new ItemStack(Material.LAVA_BUCKET)));
|
||||
registerFuelType(new MachineFuel(200, SlimefunItems.BUCKET_OF_OIL));
|
||||
registerFuelType(new MachineFuel(500, SlimefunItems.BUCKET_OF_FUEL));
|
||||
}
|
||||
else {
|
||||
registerFuel(new MachineFuel(2500, SlimefunItems.URANIUM));
|
||||
registerFuel(new MachineFuel(1200, SlimefunItems.NEPTUNIUM));
|
||||
registerFuel(new MachineFuel(3000, SlimefunItems.BOOSTED_URANIUM));
|
||||
registerFuelType(new MachineFuel(2500, SlimefunItems.URANIUM));
|
||||
registerFuelType(new MachineFuel(1200, SlimefunItems.NEPTUNIUM));
|
||||
registerFuelType(new MachineFuel(3000, SlimefunItems.BOOSTED_URANIUM));
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,7 +627,7 @@ public abstract class ProgrammableAndroid extends Android implements InventoryBl
|
||||
public List<ItemStack> getDisplayRecipes() {
|
||||
List<ItemStack> list = new ArrayList<>();
|
||||
|
||||
for (MachineFuel fuel : recipes) {
|
||||
for (MachineFuel fuel : fuelTypes) {
|
||||
ItemStack item = fuel.getInput().clone();
|
||||
ItemMeta im = item.getItemMeta();
|
||||
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 };
|
||||
}
|
||||
|
||||
public abstract AndroidType getAndroidType();
|
||||
|
||||
public abstract float getFuelEfficiency();
|
||||
|
||||
public abstract int getTier();
|
||||
@ -266,23 +695,23 @@ public abstract class ProgrammableAndroid extends Android implements InventoryBl
|
||||
BlockStorage.addBlockInfo(b, "index", String.valueOf(0));
|
||||
break;
|
||||
case TURN_LEFT:
|
||||
int indexLeft = directions.indexOf(BlockFace.valueOf(BlockStorage.getLocationInfo(b.getLocation(), "rotation"))) - 1;
|
||||
if (indexLeft < 0) indexLeft = directions.size() - 1;
|
||||
int indexLeft = POSSIBLE_ROTATIONS.indexOf(BlockFace.valueOf(BlockStorage.getLocationInfo(b.getLocation(), "rotation"))) - 1;
|
||||
if (indexLeft < 0) indexLeft = POSSIBLE_ROTATIONS.size() - 1;
|
||||
|
||||
Rotatable rotatableLeft = (Rotatable) b.getBlockData();
|
||||
rotatableLeft.setRotation(directions.get(indexLeft));
|
||||
rotatableLeft.setRotation(POSSIBLE_ROTATIONS.get(indexLeft));
|
||||
b.setBlockData(rotatableLeft);
|
||||
BlockStorage.addBlockInfo(b, "rotation", directions.get(indexLeft).toString());
|
||||
BlockStorage.addBlockInfo(b, "rotation", POSSIBLE_ROTATIONS.get(indexLeft).toString());
|
||||
|
||||
break;
|
||||
case TURN_RIGHT:
|
||||
int indexRight = directions.indexOf(BlockFace.valueOf(BlockStorage.getLocationInfo(b.getLocation(), "rotation"))) + 1;
|
||||
if (indexRight == directions.size()) indexRight = 0;
|
||||
int indexRight = POSSIBLE_ROTATIONS.indexOf(BlockFace.valueOf(BlockStorage.getLocationInfo(b.getLocation(), "rotation"))) + 1;
|
||||
if (indexRight == POSSIBLE_ROTATIONS.size()) indexRight = 0;
|
||||
|
||||
Rotatable rotatableRight = (Rotatable) b.getBlockData();
|
||||
rotatableRight.setRotation(directions.get(indexRight));
|
||||
rotatableRight.setRotation(POSSIBLE_ROTATIONS.get(indexRight));
|
||||
b.setBlockData(rotatableRight);
|
||||
BlockStorage.addBlockInfo(b, "rotation", directions.get(indexRight).toString());
|
||||
BlockStorage.addBlockInfo(b, "rotation", POSSIBLE_ROTATIONS.get(indexRight).toString());
|
||||
|
||||
break;
|
||||
case DIG_FORWARD:
|
||||
@ -375,7 +804,7 @@ public abstract class ProgrammableAndroid extends Android implements InventoryBl
|
||||
ItemStack item = menu.getItemInSlot(43);
|
||||
|
||||
if (item != null) {
|
||||
for (MachineFuel fuel : recipes) {
|
||||
for (MachineFuel fuel : fuelTypes) {
|
||||
if (fuel.test(item)) {
|
||||
menu.consumeItem(43);
|
||||
|
||||
@ -425,25 +854,11 @@ public abstract class ProgrammableAndroid extends Android implements InventoryBl
|
||||
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) {
|
||||
for (int i : border) {
|
||||
for (int i : BORDER) {
|
||||
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());
|
||||
}
|
||||
|
||||
@ -483,8 +898,50 @@ public abstract class ProgrammableAndroid extends Android implements InventoryBl
|
||||
}
|
||||
}
|
||||
|
||||
public void registerFuel(MachineFuel fuel) {
|
||||
this.recipes.add(fuel);
|
||||
public void registerFuelType(MachineFuel 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
|
||||
public void tick(Block b, SlimefunItem sf, Config data) {
|
||||
if (BlockStorage.getLocationInfo(b.getLocation(), "enabled").equals("false")) return;
|
||||
|
||||
if (lifetime % 60 == 0) {
|
||||
if (ChargableBlock.getCharge(b) < ENERGY_CONSUMPTION) return;
|
||||
|
||||
int soulsand = 0;
|
||||
int skulls = 0;
|
||||
if ("false".equals(BlockStorage.getLocationInfo(b.getLocation(), "enabled"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (lifetime % 60 == 0 && ChargableBlock.getCharge(b) >= ENERGY_CONSUMPTION) {
|
||||
BlockMenu menu = BlockStorage.getInventory(b);
|
||||
|
||||
for (int slot : getSoulSandSlots()) {
|
||||
if (SlimefunUtils.isItemSimilar(menu.getItemInSlot(slot), new ItemStack(Material.SOUL_SAND), true)) {
|
||||
soulsand = soulsand + menu.getItemInSlot(slot).getAmount();
|
||||
boolean soulsand = findResource(menu, Material.SOUL_SAND, 4, getSoulSandSlots());
|
||||
boolean skulls = findResource(menu, Material.WITHER_SKELETON_SKULL, 3, getWitherSkullSlots());
|
||||
|
||||
if (soulsand > 3) {
|
||||
soulsand = 4;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (soulsand && skulls) {
|
||||
consumeResources(menu);
|
||||
|
||||
ChargableBlock.addCharge(b, -ENERGY_CONSUMPTION);
|
||||
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.ItemStack;
|
||||
|
||||
import io.github.thebusybiscuit.cscorelib2.inventory.InvUtils;
|
||||
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
|
||||
import me.mrCookieSlime.Slimefun.SlimefunPlugin;
|
||||
import me.mrCookieSlime.Slimefun.Lists.SlimefunItems;
|
||||
@ -45,9 +44,9 @@ public class OreWasher extends MultiBlockMachine {
|
||||
Dispenser disp = (Dispenser) dispBlock.getState();
|
||||
Inventory inv = disp.getInventory();
|
||||
|
||||
for (ItemStack current : inv.getContents()) {
|
||||
if (current != null) {
|
||||
if (SlimefunUtils.isItemSimilar(current, SlimefunItems.SIFTED_ORE, true)) {
|
||||
for (ItemStack input : inv.getContents()) {
|
||||
if (input != null) {
|
||||
if (SlimefunUtils.isItemSimilar(input, SlimefunItems.SIFTED_ORE, true)) {
|
||||
ItemStack output = getRandomDust();
|
||||
Inventory outputInv = null;
|
||||
|
||||
@ -62,50 +61,31 @@ public class OreWasher extends MultiBlockMachine {
|
||||
ItemStack dummyAdding = SlimefunItems.DEBUG_FISH;
|
||||
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) {
|
||||
ItemStack removing = current.clone();
|
||||
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);
|
||||
outputInv.addItem(SlimefunItems.STONE_CHUNK);
|
||||
}
|
||||
else SlimefunPlugin.getLocal().sendMessage(p, "machines.full-inventory", true);
|
||||
|
||||
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;
|
||||
Inventory outputInv = findOutputInventory(output, dispBlock, inv);
|
||||
|
||||
if (outputInv != null) {
|
||||
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);
|
||||
removeItem(p, b, inv, outputInv, input, output, 2);
|
||||
|
||||
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;
|
||||
Inventory outputInv = findOutputInventory(output, dispBlock, inv);
|
||||
|
||||
if (outputInv != null) {
|
||||
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);
|
||||
removeItem(p, b, inv, outputInv, input, output, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -114,6 +94,21 @@ public class OreWasher extends MultiBlockMachine {
|
||||
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.
|
||||
*
|
||||
|
@ -57,19 +57,7 @@ class ExplosiveTool extends SimpleSlimefunItem<BlockBreakHandler> implements Not
|
||||
e.getBlock().getWorld().createExplosion(e.getBlock().getLocation(), 0.0F);
|
||||
e.getBlock().getWorld().playSound(e.getBlock().getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 0.2F, 1F);
|
||||
|
||||
List<Block> blocks = new ArrayList<>();
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
List<Block> blocks = findBlocks(e.getBlock());
|
||||
|
||||
if (callExplosionEvent.getValue().booleanValue()) {
|
||||
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
|
||||
public boolean isDamageable() {
|
||||
return damageOnUse.getValue();
|
||||
|
@ -9,6 +9,8 @@ import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
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 me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
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.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 PickaxeOfContainment(Category category, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
|
||||
@ -47,9 +57,26 @@ public class PickaxeOfContainment extends SimpleSlimefunItem<BlockBreakHandler>
|
||||
return true;
|
||||
}
|
||||
|
||||
ItemStack spawner = breakSpawner(b);
|
||||
b.getLocation().getWorld().dropItemNaturally(b.getLocation(), spawner);
|
||||
|
||||
e.setExpToDrop(0);
|
||||
e.setDropItems(false);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (e.getBlock().getType() == Material.SPAWNER) e.setDropItems(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
@ -65,17 +92,7 @@ public class PickaxeOfContainment extends SimpleSlimefunItem<BlockBreakHandler>
|
||||
|
||||
im.setLore(lore);
|
||||
spawner.setItemMeta(im);
|
||||
b.getLocation().getWorld().dropItemNaturally(b.getLocation(), spawner);
|
||||
e.setExpToDrop(0);
|
||||
e.setDropItems(false);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (e.getBlock().getType() == Material.SPAWNER) e.setDropItems(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
return spawner;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import java.util.List;
|
||||
import org.bukkit.Effect;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
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.materials.MaterialCollections;
|
||||
import io.github.thebusybiscuit.cscorelib2.protection.ProtectableAction;
|
||||
import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting;
|
||||
import me.mrCookieSlime.Slimefun.SlimefunPlugin;
|
||||
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
|
||||
import me.mrCookieSlime.Slimefun.Objects.Category;
|
||||
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SimpleSlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.Objects.handlers.BlockBreakHandler;
|
||||
import me.mrCookieSlime.Slimefun.api.Slimefun;
|
||||
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> {
|
||||
|
||||
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) {
|
||||
super(category, item, recipeType, recipe);
|
||||
|
||||
addItemSetting(maxBlocks);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -36,11 +59,25 @@ public class PickaxeOfVeinMining extends SimpleSlimefunItem<BlockBreakHandler> {
|
||||
|
||||
@Override
|
||||
public boolean onBlockBreak(BlockBreakEvent e, ItemStack item, int fortune, List<ItemStack> drops) {
|
||||
if (MaterialCollections.getAllOres().contains(e.getBlock().getType()) && isItem(item)) {
|
||||
List<Block> blocks = Vein.find(e.getBlock(), 16, MaterialCollections.getAllOres());
|
||||
if (!Slimefun.hasUnlocked(e.getPlayer(), PickaxeOfVeinMining.this, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
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(e.getPlayer(), b.getLocation(), ProtectableAction.BREAK_BLOCK)) {
|
||||
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())) {
|
||||
@ -50,12 +87,6 @@ public class PickaxeOfVeinMining extends SimpleSlimefunItem<BlockBreakHandler> {
|
||||
b.setType(Material.AIR);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.bukkit.Effect;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@ -36,24 +38,21 @@ public class SmeltersPickaxe extends SimpleSlimefunItem<BlockBreakHandler> imple
|
||||
|
||||
@Override
|
||||
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 (BlockStorage.hasBlockInfo(e.getBlock())) return true;
|
||||
if (!Slimefun.hasUnlocked(e.getPlayer(), SmeltersPickaxe.this, true)) return true;
|
||||
if (BlockStorage.hasBlockInfo(e.getBlock())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Collection<ItemStack> blockDrops = e.getBlock().getDrops(getItem());
|
||||
|
||||
for (ItemStack drop : blockDrops) {
|
||||
if (drop != null) {
|
||||
ItemStack output = drop;
|
||||
output.setAmount(fortune);
|
||||
|
||||
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);
|
||||
if (drop != null && drop.getType() != Material.AIR) {
|
||||
smelt(e.getBlock(), drop, fortune);
|
||||
drops.add(drop);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
public boolean isDamageable() {
|
||||
return true;
|
||||
|
@ -28,8 +28,20 @@ import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SimpleSlimefunItem;
|
||||
import me.mrCookieSlime.Slimefun.Objects.handlers.ItemUseHandler;
|
||||
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 {
|
||||
|
||||
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) {
|
||||
super(category, item, recipeType, recipe);
|
||||
}
|
||||
@ -38,45 +50,25 @@ public class SeismicAxe extends SimpleSlimefunItem<ItemUseHandler> implements No
|
||||
public ItemUseHandler getItemHandler() {
|
||||
return e -> {
|
||||
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++) {
|
||||
Block b = blocks.get(i);
|
||||
Location ground = b.getLocation();
|
||||
for (int i = 2; i < blocks.size(); i++) {
|
||||
Block ground = findGround(blocks.get(i));
|
||||
Location groundLocation = ground.getLocation();
|
||||
|
||||
if (b.getType() == null || b.getType() == Material.AIR) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
ground.getWorld().playEffect(groundLocation, Effect.STEP_SOUND, ground.getType());
|
||||
|
||||
b.getWorld().playEffect(ground, Effect.STEP_SOUND, ground.getBlock().getType());
|
||||
|
||||
if (ground.getBlock().getRelative(BlockFace.UP).getType() == null || ground.getBlock().getRelative(BlockFace.UP).getType() == Material.AIR) {
|
||||
Location loc = ground.getBlock().getRelative(BlockFace.UP).getLocation().add(0.5, 0.0, 0.5);
|
||||
FallingBlock block = ground.getWorld().spawnFallingBlock(loc, ground.getBlock().getBlockData());
|
||||
if (ground.getRelative(BlockFace.UP).getType() == Material.AIR) {
|
||||
Location loc = ground.getRelative(BlockFace.UP).getLocation().add(0.5, 0.0, 0.5);
|
||||
FallingBlock block = ground.getWorld().spawnFallingBlock(loc, ground.getBlockData());
|
||||
block.setDropItem(false);
|
||||
block.setVelocity(new Vector(0, 0.4 + i * 0.01, 0));
|
||||
block.setMetadata("seismic_axe", new FixedMetadataValue(SlimefunPlugin.instance, "fake_block"));
|
||||
}
|
||||
|
||||
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())) {
|
||||
Vector vector = n.getLocation().toVector().subtract(p.getLocation().toVector()).normalize().multiply(1.4);
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (n instanceof LivingEntity && n.getType() != EntityType.ARMOR_STAND && n.getLocation().distance(groundLocation) <= 2.0D && !n.getUniqueId().equals(p.getUniqueId())) {
|
||||
pushEntity(p, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
public boolean isDamageable() {
|
||||
return true;
|
||||
|
@ -35,6 +35,7 @@ public class SeismicAxeListener implements Listener {
|
||||
|
||||
if (e.getEntity().getType() == EntityType.FALLING_BLOCK && e.getEntity().hasMetadata("seismic_axe")) {
|
||||
e.setCancelled(true);
|
||||
e.getEntity().removeMetadata("seismic_axe", SlimefunPlugin.instance);
|
||||
e.getEntity().remove();
|
||||
}
|
||||
}
|
||||
|
@ -199,32 +199,16 @@ public final class PostSetup {
|
||||
Smeltery smeltery = (Smeltery) SlimefunItems.SMELTERY.getItem();
|
||||
|
||||
if (smeltery != null && !smeltery.isDisabled()) {
|
||||
MakeshiftSmeltery makeshiftSmeltery = ((MakeshiftSmeltery) SlimefunItems.MAKESHIFT_SMELTERY.getItem());
|
||||
ItemStack[] input = null;
|
||||
|
||||
for (ItemStack[] recipe : smeltery.getRecipes()) {
|
||||
for (ItemStack[] output : smeltery.getRecipes()) {
|
||||
if (input == null) {
|
||||
input = recipe;
|
||||
input = output;
|
||||
}
|
||||
else {
|
||||
if (input[0] != null && recipe[0] != null) {
|
||||
List<ItemStack> inputs = new ArrayList<>();
|
||||
|
||||
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] });
|
||||
}
|
||||
if (input[0] != null && output[0] != null) {
|
||||
addSmelteryRecipe(input, output, makeshiftSmeltery);
|
||||
}
|
||||
|
||||
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) {
|
||||
SlimefunItem sfItem = SlimefunItem.getByItem(item);
|
||||
return sfItem != null && sfItem.getID().endsWith("_DUST");
|
||||
|
@ -19,6 +19,8 @@ import org.bukkit.inventory.meta.ItemMeta;
|
||||
*/
|
||||
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 boolean hasItemMeta;
|
||||
|
||||
@ -49,37 +51,37 @@ public final class ItemStackWrapper extends ItemStack {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
throw new UnsupportedOperationException("ItemStackWrappers do not allow .equals()");
|
||||
throw new UnsupportedOperationException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
throw new UnsupportedOperationException("You cannot hash an ItemStackWrapper");
|
||||
throw new UnsupportedOperationException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack clone() {
|
||||
throw new UnsupportedOperationException("You cannot clone an ItemStackWrapper");
|
||||
throw new UnsupportedOperationException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setType(Material type) {
|
||||
throw new UnsupportedOperationException("ItemStackWrappers are immutable and not indended for actual usage.");
|
||||
throw new UnsupportedOperationException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAmount(int amount) {
|
||||
throw new UnsupportedOperationException("ItemStackWrappers are immutable and not indended for actual usage.");
|
||||
throw new UnsupportedOperationException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setItemMeta(ItemMeta itemMeta) {
|
||||
throw new UnsupportedOperationException("ItemStackWrappers are immutable and not indended for actual usage.");
|
||||
throw new UnsupportedOperationException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
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