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

RecipeChoice task is now thread-safe

This commit is contained in:
TheBusyBiscuit 2021-02-06 00:29:57 +01:00
parent a25b470272
commit 2d050a8e35
7 changed files with 58 additions and 23 deletions

View File

@ -41,7 +41,7 @@ import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlock;
import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlockMachine;
import io.github.thebusybiscuit.slimefun4.core.researching.Research;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.RecipeChoiceTask;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.AsyncRecipeChoiceTask;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.SlimefunGuideItem;
@ -408,7 +408,7 @@ public class SurvivalSlimefunGuide implements SlimefunGuideImplementation {
ItemStack result = null;
Optional<MinecraftRecipe<? super Recipe>> optional = MinecraftRecipe.of(recipe);
RecipeChoiceTask task = new RecipeChoiceTask();
AsyncRecipeChoiceTask task = new AsyncRecipeChoiceTask();
if (optional.isPresent()) {
showRecipeChoices(recipe, recipeItems, task);
@ -454,7 +454,7 @@ public class SurvivalSlimefunGuide implements SlimefunGuideImplementation {
}
}
private <T extends Recipe> void showRecipeChoices(T recipe, ItemStack[] recipeItems, RecipeChoiceTask task) {
private <T extends Recipe> void showRecipeChoices(T recipe, ItemStack[] recipeItems, AsyncRecipeChoiceTask task) {
RecipeChoice[] choices = SlimefunPlugin.getMinecraftRecipeService().getRecipeShape(recipe);
if (choices.length == 1 && choices[0] instanceof MaterialChoice) {
@ -496,7 +496,7 @@ public class SurvivalSlimefunGuide implements SlimefunGuideImplementation {
});
}
RecipeChoiceTask task = new RecipeChoiceTask();
AsyncRecipeChoiceTask task = new AsyncRecipeChoiceTask();
if (addToHistory) {
profile.getGuideHistory().add(item);
@ -519,7 +519,7 @@ public class SurvivalSlimefunGuide implements SlimefunGuideImplementation {
}
}
private void displayItem(ChestMenu menu, PlayerProfile profile, Player p, Object item, ItemStack output, RecipeType recipeType, ItemStack[] recipe, RecipeChoiceTask task) {
private void displayItem(ChestMenu menu, PlayerProfile profile, Player p, Object item, ItemStack output, RecipeType recipeType, ItemStack[] recipe, AsyncRecipeChoiceTask task) {
addBackButton(menu, 0, p, profile);
MenuClickHandler clickHandler = (pl, slot, itemstack, action) -> {

View File

@ -31,7 +31,7 @@ import io.github.thebusybiscuit.slimefun4.core.attributes.EnergyNetComponent;
import io.github.thebusybiscuit.slimefun4.core.handlers.BlockUseHandler;
import io.github.thebusybiscuit.slimefun4.core.networks.energy.EnergyNetComponentType;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.RecipeChoiceTask;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.AsyncRecipeChoiceTask;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
@ -205,7 +205,7 @@ public abstract class AbstractAutoCrafter extends SlimefunItem implements Energy
return false;
});
RecipeChoiceTask task = new RecipeChoiceTask();
AsyncRecipeChoiceTask task = new AsyncRecipeChoiceTask();
recipe.show(menu, task);
menu.open(p);

View File

@ -13,7 +13,7 @@ import org.bukkit.inventory.Recipe;
import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.ShapelessRecipe;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.RecipeChoiceTask;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.AsyncRecipeChoiceTask;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
@ -42,7 +42,7 @@ public abstract class AbstractRecipe {
return result;
}
public abstract void show(@Nonnull ChestMenu menu, @Nonnull RecipeChoiceTask task);
public abstract void show(@Nonnull ChestMenu menu, @Nonnull AsyncRecipeChoiceTask task);
@Nullable
public static AbstractRecipe of(@Nullable Recipe recipe) {

View File

@ -7,7 +7,7 @@ import javax.annotation.Nonnull;
import org.bukkit.inventory.ItemStack;
import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.EnhancedCraftingTable;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.RecipeChoiceTask;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.AsyncRecipeChoiceTask;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
@ -39,7 +39,7 @@ class EnhancedRecipe extends AbstractRecipe {
}
@Override
public void show(@Nonnull ChestMenu menu, @Nonnull RecipeChoiceTask task) {
public void show(@Nonnull ChestMenu menu, @Nonnull AsyncRecipeChoiceTask task) {
menu.addItem(24, getResult().clone(), ChestMenuUtils.getEmptyClickHandler());
ItemStack[] recipe = item.getRecipe();

View File

@ -21,12 +21,14 @@ import org.bukkit.inventory.ShapelessRecipe;
import io.github.thebusybiscuit.cscorelib2.data.PersistentDataAPI;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.AsyncRecipeChoiceTask;
import io.github.thebusybiscuit.slimefun4.utils.PatternUtils;
import io.papermc.lib.PaperLib;
import me.mrCookieSlime.Slimefun.Lists.RecipeType;
import me.mrCookieSlime.Slimefun.Objects.Category;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.SlimefunItem;
import me.mrCookieSlime.Slimefun.api.SlimefunItemStack;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
public class VanillaAutoCrafter extends AbstractAutoCrafter {
@ -91,6 +93,11 @@ public class VanillaAutoCrafter extends AbstractAutoCrafter {
}
}
@ParametersAreNonnullByDefault
private void offerRecipe(Player p, Block b, List<Recipe> recipes, int page, BlockMenu menu, AsyncRecipeChoiceTask task) {
}
@Nonnull
private List<Recipe> getRecipesFor(@Nonnull ItemStack item) {
List<Recipe> recipes = new ArrayList<>();

View File

@ -15,7 +15,7 @@ import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.ShapelessRecipe;
import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.RecipeChoiceTask;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.AsyncRecipeChoiceTask;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import me.mrCookieSlime.CSCoreLibPlugin.general.Inventory.ChestMenu;
@ -68,7 +68,7 @@ class VanillaRecipe extends AbstractRecipe {
}
@Override
public void show(@Nonnull ChestMenu menu, @Nonnull RecipeChoiceTask task) {
public void show(@Nonnull ChestMenu menu, @Nonnull AsyncRecipeChoiceTask task) {
menu.addItem(24, getResult().clone(), ChestMenuUtils.getEmptyClickHandler());
RecipeChoice[] choices = SlimefunPlugin.getMinecraftRecipeService().getRecipeShape(recipe);
ItemStack[] items = new ItemStack[9];

View File

@ -2,6 +2,8 @@ package io.github.thebusybiscuit.slimefun4.implementation.tasks;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.annotation.Nonnull;
@ -19,7 +21,7 @@ import io.github.thebusybiscuit.slimefun4.implementation.SlimefunPlugin;
import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunGuide;
/**
* A {@link RecipeChoiceTask} is an asynchronously repeating task that cycles
* A {@link AsyncRecipeChoiceTask} is an asynchronously repeating task that cycles
* through the different variants of {@link Material} that a {@link MaterialChoice} or {@link Tag} can represent.
*
* It is used in the {@link SurvivalSlimefunGuide} for any {@link ItemStack} from Minecraft
@ -28,11 +30,13 @@ import io.github.thebusybiscuit.slimefun4.implementation.guide.SurvivalSlimefunG
* @author TheBusyBiscuit
*
*/
public class RecipeChoiceTask implements Runnable {
public class AsyncRecipeChoiceTask implements Runnable {
private static final int UPDATE_INTERVAL = 14;
private final Map<Integer, LoopIterator<Material>> iterators = new HashMap<>();
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private Inventory inventory;
private int id;
@ -52,13 +56,25 @@ public class RecipeChoiceTask implements Runnable {
public void add(int slot, @Nonnull MaterialChoice choice) {
Validate.notNull(choice, "Cannot add a null RecipeChoice");
iterators.put(slot, new LoopIterator<>(choice.getChoices()));
lock.writeLock().lock();
try {
iterators.put(slot, new LoopIterator<>(choice.getChoices()));
} finally {
lock.writeLock().unlock();
}
}
public void add(int slot, @Nonnull Tag<Material> tag) {
Validate.notNull(tag, "Cannot add a null Tag");
iterators.put(slot, new LoopIterator<>(tag.getValues()));
lock.writeLock().lock();
try {
iterators.put(slot, new LoopIterator<>(tag.getValues()));
} finally {
lock.writeLock().unlock();
}
}
/**
@ -67,7 +83,13 @@ public class RecipeChoiceTask implements Runnable {
* @return Whether this task has nothing to do
*/
public boolean isEmpty() {
return iterators.isEmpty();
lock.readLock().lock();
try {
return iterators.isEmpty();
} finally {
lock.readLock().unlock();
}
}
@Override
@ -78,8 +100,14 @@ public class RecipeChoiceTask implements Runnable {
return;
}
for (Map.Entry<Integer, LoopIterator<Material>> entry : iterators.entrySet()) {
inventory.setItem(entry.getKey(), new ItemStack(entry.getValue().next()));
lock.readLock().lock();
try {
for (Map.Entry<Integer, LoopIterator<Material>> entry : iterators.entrySet()) {
inventory.setItem(entry.getKey(), new ItemStack(entry.getValue().next()));
}
} finally {
lock.readLock().unlock();
}
}