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

Various improvements, including Pull Request #1790

This commit is contained in:
TheBusyBiscuit 2020-04-23 13:01:47 +02:00
parent dfb47ddfbb
commit a04676b27c
13 changed files with 123 additions and 51 deletions

View File

@ -48,6 +48,8 @@
* GEO Miner is now 2 seconds faster
* All Generators will now stop consuming fuel if no energy is needed
* /sf teleporter will now open your own Teleporter Menu if you specify no Player
* Added counter-measures against Players who design Cargo networks in a way that intentionally lags out servers
* API requests to Mojang are now spread across a longer time period to prevent rate-limits
#### Fixes
* Fixed error message when clicking empty slots in the Slimefun Guide

View File

@ -216,7 +216,7 @@
<dependency>
<groupId>com.github.thebusybiscuit</groupId>
<artifactId>CS-CoreLib2</artifactId>
<version>0.14</version>
<version>0.15</version>
<scope>compile</scope>
</dependency>
<dependency>

View File

@ -1,11 +1,17 @@
package io.github.thebusybiscuit.slimefun4.api;
import java.util.Collection;
import java.util.Locale;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.bukkit.NamespacedKey;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import me.mrCookieSlime.Slimefun.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
/**
@ -89,4 +95,15 @@ public interface SlimefunAddon {
return description.getDepend().contains(dependency) || description.getSoftDepend().contains(dependency);
}
/**
* This returns a {@link Collection} holding every {@link Category} that can be directly
* linked to this {@link SlimefunAddon} based on its {@link NamespacedKey}.
*
* @return A {@link Collection} of every {@link Category} from this addon
*/
default Collection<Category> getCategories() {
String namespace = getJavaPlugin().getName().toLowerCase(Locale.ROOT);
return SlimefunPlugin.getRegistry().getCategories().stream().filter(cat -> cat.getKey().getNamespace().equals(namespace)).collect(Collectors.toList());
}
}

View File

@ -73,7 +73,7 @@ public final class SlimefunGuideSettings {
return false;
});
menu.addItem(2, new CustomItem(SkullItem.fromBase64("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTk1MmQyYjNmMzUxYTZiMDQ4N2NjNTlkYjMxYmY1ZjI2NDExMzNlNWJhMDAwNmIxODU3NmU5OTZhMDI5M2U1MiJ9fX0="), "&c" + SlimefunPlugin.getLocal().getMessage(p, "guide.title.credits"), "", "&7Contributors: &e" + SlimefunPlugin.getGitHubService().getContributors().size(), "", "&7Slimefun is an open-source project", "&7and maintained by a large community.", "&7Here you can find them all", "", "&7\u21E8 &eClick to see our contributors"), (pl, slot, action, item) -> {
menu.addItem(2, new CustomItem(SkullItem.fromHash("e952d2b3f351a6b0487cc59db31bf5f2641133e5ba0006b18576e996a0293e52"), "&c" + SlimefunPlugin.getLocal().getMessage(p, "guide.title.credits"), "", "&7Contributors: &e" + SlimefunPlugin.getGitHubService().getContributors().size(), "", "&7Slimefun is an open-source project", "&7and maintained by a large community of people.", "&7Here you can see who helped shape the project.", "", "&7\u21E8 &eClick to see our contributors"), (pl, slot, action, item) -> {
ContributorsMenu.open(pl, 0);
return false;
});

View File

@ -1,32 +0,0 @@
package io.github.thebusybiscuit.slimefun4.core.networks.cargo;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import me.mrCookieSlime.Slimefun.SlimefunPlugin;
import org.bukkit.Material;
import org.bukkit.block.Block;
final class BlockUtils {
private BlockUtils() {}
public static boolean hasInventory(Block block) {
if (block == null) return false;
Material type = block.getType();
switch (type) {
case CHEST:
case TRAPPED_CHEST:
case FURNACE:
case DISPENSER:
case DROPPER:
case HOPPER:
case BREWING_STAND:
return true;
default:
if (type.name().endsWith("SHULKER_BOX")) return true;
return (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14) &&
(type == Material.BARREL || type == Material.BLAST_FURNACE || type == Material.LECTERN || type == Material.SMOKER));
}
}
}

View File

@ -27,7 +27,7 @@ import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
public class CargoNet extends ChestTerminalNetwork {
private static final int RANGE = 5;
private static final int TICK_DELAY = SlimefunPlugin.getCfg().getInt("URID.cargo-network-tick-delay");
private static final int TICK_DELAY = SlimefunPlugin.getCfg().getInt("networks.cargo-ticker-delay");
private final Set<Location> inputNodes = new HashSet<>();
private final Set<Location> outputNodes = new HashSet<>();
@ -183,7 +183,9 @@ public class CargoNet extends ChestTerminalNetwork {
tickDelayThreshold++;
return;
}
tickDelayThreshold = 0; // reset, so we can start skipping again
// Reset the internal threshold, so we can start skipping again
tickDelayThreshold = 0;
Map<Location, Integer> inputs = new HashMap<>();
Set<Location> providers = new HashSet<>();
@ -208,6 +210,7 @@ public class CargoNet extends ChestTerminalNetwork {
// (Apart from ChestTerminal Buses)
for (Map.Entry<Location, Integer> entry : inputs.entrySet()) {
Location input = entry.getKey();
Optional<Block> attachedBlock = getAttachedBlock(input.getBlock());
if (!attachedBlock.isPresent()) {
continue;
@ -231,11 +234,14 @@ public class CargoNet extends ChestTerminalNetwork {
if (roundrobin) {
int index = roundRobin.getOrDefault(input, 0);
if (index < outputlist.size()) {
for (int i = 0; i < index; i++) {
Location temp = outputlist.remove(0);
outputlist.add(temp);
}
index++;
}
else {
@ -260,7 +266,7 @@ public class CargoNet extends ChestTerminalNetwork {
if (menu != null) {
menu.replaceExistingItem(previousSlot, stack);
}
else if (BlockUtils.hasInventory(inputTarget)) {
else if (CargoUtils.hasInventory(inputTarget)) {
BlockState state = inputTarget.getState();
if (state instanceof InventoryHolder) {

View File

@ -12,9 +12,11 @@ import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.api.MinecraftVersion;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.ItemStackWrapper;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import me.mrCookieSlime.Slimefun.api.inventory.DirtyChestMenu;
@ -27,11 +29,52 @@ final class CargoUtils {
private CargoUtils() {}
public static boolean hasInventory(Block block) {
if (block == null) {
return false;
}
Material type = block.getType();
switch (type) {
case CHEST:
case TRAPPED_CHEST:
case FURNACE:
case DISPENSER:
case DROPPER:
case HOPPER:
case BREWING_STAND:
case SHULKER_BOX:
return true;
default:
break;
}
if (type.name().endsWith("_SHULKER_BOX")) {
return true;
}
if (SlimefunPlugin.getMinecraftVersion().isAtLeast(MinecraftVersion.MINECRAFT_1_14)) {
switch (type) {
case BARREL:
case BLAST_FURNACE:
case SMOKER:
return true;
default:
break;
}
}
return false;
}
public static ItemStack withdraw(Block node, Block target, ItemStack template) {
DirtyChestMenu menu = getChestMenu(target);
if (menu == null) {
if (BlockUtils.hasInventory(target)) {
if (hasInventory(target)) {
BlockState state = target.getState();
if (state instanceof InventoryHolder) {
return withdrawFromVanillaInventory(node, template, ((InventoryHolder) state).getInventory());
}
@ -106,7 +149,7 @@ final class CargoUtils {
}
}
}
else if (BlockUtils.hasInventory(target)) {
else if (hasInventory(target)) {
BlockState state = target.getState();
if (state instanceof InventoryHolder) {
@ -141,13 +184,16 @@ final class CargoUtils {
if (!matchesFilter(node, stack, index)) return stack;
DirtyChestMenu menu = getChestMenu(target);
if (menu == null) {
if (BlockUtils.hasInventory(target)) {
if (hasInventory(target)) {
BlockState state = target.getState();
if (state instanceof InventoryHolder) {
return insertIntoVanillaInventory(stack, ((InventoryHolder) state).getInventory());
}
}
return stack;
}
@ -162,6 +208,7 @@ final class CargoUtils {
int maxStackSize = itemInSlot.getType().getMaxStackSize();
int currentAmount = itemInSlot.getAmount();
if (SlimefunUtils.isItemSimilar(itemInSlot, wrapper, true, false) && currentAmount < maxStackSize) {
int amount = currentAmount + stack.getAmount();
@ -183,7 +230,7 @@ final class CargoUtils {
private static ItemStack insertIntoVanillaInventory(ItemStack stack, Inventory inv) {
ItemStack[] contents = inv.getContents();
int minSlot = 0;
int minSlot = 0;
int maxSlot = contents.length;
// Check if it is a normal furnace
@ -198,17 +245,18 @@ final class CargoUtils {
}
}
else if (inv instanceof BrewerInventory) {
// Check if it goes in the potion slot,
if (stack.getType() == Material.POTION || stack.getType() == Material.LINGERING_POTION || stack.getType() == Material.SPLASH_POTION) {
// Potions slot
maxSlot = 3;
// The blaze powder slot,
}
else if (stack.getType() == Material.BLAZE_POWDER) {
// Blaze Powder slot
minSlot = 4;
maxSlot = 5;
}
else {
// Or the input
// Input slot
minSlot = 3;
maxSlot = 4;
}

View File

@ -254,7 +254,7 @@ abstract class ChestTerminalNetwork extends Network {
handleWithdraw(blockMenu, items, l);
}
}
else if (BlockUtils.hasInventory(target)) {
else if (CargoUtils.hasInventory(target)) {
BlockState state = target.getState();
if (state instanceof InventoryHolder) {

View File

@ -46,7 +46,7 @@ public class AutoSavingService {
* This method saves every {@link PlayerProfile} in memory and removes profiles
* that were markes for deletion.
*/
public void saveAllPlayers() {
private void saveAllPlayers() {
Iterator<PlayerProfile> iterator = PlayerProfile.iterator();
int players = 0;
@ -71,7 +71,7 @@ public class AutoSavingService {
/**
* This method saves the data of every {@link Block} marked dirty by {@link BlockStorage}.
*/
public void saveAllBlocks() {
private void saveAllBlocks() {
Set<BlockStorage> worlds = new HashSet<>();
for (World world : Bukkit.getWorlds()) {

View File

@ -50,6 +50,7 @@ public class GitHubService {
private void addDefaultContributors() {
addContributor("Fuffles_", "&dArtist");
addContributor("IMS_Art", "&dArtist");
addContributor("nahkd123", "&aWinner of the 2020 Addon Jam");
new Translators(contributors);
}

View File

@ -5,9 +5,14 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import io.github.thebusybiscuit.cscorelib2.players.MinecraftAccount;
import io.github.thebusybiscuit.cscorelib2.players.MinecraftAccount.TooManyRequestsException;
import me.mrCookieSlime.Slimefun.SlimefunPlugin;
import me.mrCookieSlime.Slimefun.api.Slimefun;
/**
* This {@link GitHubTask} represents a {@link Runnable} that is run every X minutes.
@ -21,6 +26,8 @@ import io.github.thebusybiscuit.cscorelib2.players.MinecraftAccount.TooManyReque
*/
class GitHubTask implements Runnable {
private static final int MAX_REQUESTS_PER_MINUTE = 12;
private final GitHubService gitHubService;
GitHubTask(GitHubService github) {
@ -31,9 +38,14 @@ class GitHubTask implements Runnable {
public void run() {
gitHubService.getConnectors().forEach(GitHubConnector::pullFile);
grabTextures();
}
private void grabTextures() {
// 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;
for (Contributor contributor : gitHubService.getContributors().values()) {
if (!contributor.hasTexture()) {
@ -43,18 +55,33 @@ class GitHubTask implements Runnable {
}
else {
contributor.setTexture(grabTexture(skins, contributor.getMinecraftName()));
count++;
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 (Exception x) {
catch (IOException | TooManyRequestsException x) {
// Too many requests
break;
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 2 minutes
Bukkit.getScheduler().runTaskLaterAsynchronously(SlimefunPlugin.instance, this::grabTextures, 2 * 60 * 20L);
return;
}
}
}
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, 60 * 20L);
}
}
private String grabTexture(Map<String, String> skins, String username) throws TooManyRequestsException, IOException {

View File

@ -162,7 +162,7 @@ public final class SlimefunPlugin extends JavaPlugin implements SlimefunAddon {
// Setting up Networks
gpsNetwork = new GPSNetwork();
networkManager = new NetworkManager(config.getInt("options.max-network-size"));
networkManager = new NetworkManager(config.getInt("networks.max-size"));
// Setting up bStats
metricsService.start();

View File

@ -28,10 +28,13 @@ researches:
URID:
info-delay: 3000
cargo-network-tick-delay: 0
custom-ticker-delay: 12
enable-tickers: true
networks:
max-size: 200
cargo-ticker-delay: 0
items:
talismans: true
backpacks: true