Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow items to be unlocked in recipe menu #3628

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@

import io.github.thebusybiscuit.slimefun4.api.events.PlayerPreResearchEvent;
import io.github.thebusybiscuit.slimefun4.api.events.ResearchUnlockEvent;
import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup;
import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
import io.github.thebusybiscuit.slimefun4.api.player.PlayerProfile;
import io.github.thebusybiscuit.slimefun4.core.guide.SlimefunGuideImplementation;
import io.github.thebusybiscuit.slimefun4.core.guide.options.SlimefunGuideSettings;
import io.github.thebusybiscuit.slimefun4.core.services.localization.Language;
import io.github.thebusybiscuit.slimefun4.implementation.Slimefun;
import io.github.thebusybiscuit.slimefun4.implementation.setup.ResearchSetup;
Expand Down Expand Up @@ -209,24 +209,29 @@ public List<SlimefunItem> getAffectedItems() {
* The {@link PlayerProfile} of that {@link Player}.
* @param sfItem
* The {@link SlimefunItem} on which the {@link Player} clicked.
* @param itemGroup
* The {@link ItemGroup} where the {@link Player} was.
* @param page
* The page number of where the {@link Player} was in the {@link ItemGroup};
* @param callback
* The action to perform after unlocking this item.
*
*/
@ParametersAreNonnullByDefault
public void unlockFromGuide(SlimefunGuideImplementation guide, Player player, PlayerProfile profile, SlimefunItem sfItem, ItemGroup itemGroup, int page) {
public void unlockFromGuide(SlimefunGuideImplementation guide, Player player, PlayerProfile profile, SlimefunItem sfItem, Consumer<Player> callback) {
if (!Slimefun.getRegistry().getCurrentlyResearchingPlayers().contains(player.getUniqueId())) {
if (profile.hasUnlocked(this)) {
guide.openItemGroup(profile, itemGroup, page);
callback.accept(player);
} else {
PlayerPreResearchEvent event = new PlayerPreResearchEvent(player, this, sfItem);
Bukkit.getPluginManager().callEvent(event);

if (!event.isCancelled()) {
if (this.canUnlock(player)) {
guide.unlockItem(player, sfItem, pl -> guide.openItemGroup(profile, itemGroup, page));
if (player.getGameMode() == GameMode.CREATIVE && Slimefun.getRegistry().isFreeCreativeResearchingEnabled()) {
unlock(player, true, callback);
} else {
player.setLevel(player.getLevel() - this.getCost());

boolean skipLearningAnimation = Slimefun.getRegistry().isLearningAnimationDisabled() || !SlimefunGuideSettings.hasLearningAnimationEnabled(player);
unlock(player, skipLearningAnimation, callback);
}
svr333 marked this conversation as resolved.
Show resolved Hide resolved
} else {
Slimefun.getLocalization().sendMessage(player, "messages.not-enough-xp", true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,4 @@ public interface SlimefunGuideImplementation {
@ParametersAreNonnullByDefault
void displayItem(PlayerProfile profile, SlimefunItem item, boolean addToHistory);

@ParametersAreNonnullByDefault
default void unlockItem(Player p, SlimefunItem sfitem, Consumer<Player> callback) {
Research research = sfitem.getResearch();

if (p.getGameMode() == GameMode.CREATIVE && Slimefun.getRegistry().isFreeCreativeResearchingEnabled()) {
research.unlock(p, true, callback);
} else {
p.setLevel(p.getLevel() - research.getCost());

boolean skipLearningAnimation = Slimefun.getRegistry().isLearningAnimationDisabled() || !SlimefunGuideSettings.hasLearningAnimationEnabled(p);
research.unlock(p, skipLearningAnimation, callback);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import io.github.thebusybiscuit.slimefun4.core.guide.options.SlimefunGuideSettings;
import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlock;
import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlockMachine;
import io.github.thebusybiscuit.slimefun4.core.services.localization.SlimefunLocalization;
import io.github.thebusybiscuit.slimefun4.core.services.sounds.SoundEffect;
import io.github.thebusybiscuit.slimefun4.implementation.Slimefun;
import io.github.thebusybiscuit.slimefun4.implementation.tasks.AsyncRecipeChoiceTask;
Expand Down Expand Up @@ -289,9 +290,9 @@ private void displaySlimefunItem(ChestMenu menu, ItemGroup itemGroup, Player p,
menu.addItem(index, new CustomItemStack(ChestMenuUtils.getNoPermissionItem(), sfitem.getItemName(), message.toArray(new String[0])));
menu.addMenuClickHandler(index, ChestMenuUtils.getEmptyClickHandler());
} else if (isSurvivalMode() && research != null && !profile.hasUnlocked(research)) {
menu.addItem(index, new CustomItemStack(ChestMenuUtils.getNotResearchedItem(), ChatColor.WHITE + ItemUtils.getItemName(sfitem.getItem()), "&4&l" + Slimefun.getLocalization().getMessage(p, "guide.locked"), "", "&a> Click to unlock", "", "&7Cost: &b" + research.getCost() + " Level(s)"));
menu.addItem(index, createLockedItem(p, sfitem, research));
menu.addMenuClickHandler(index, (pl, slot, item, action) -> {
research.unlockFromGuide(this, p, profile, sfitem, itemGroup, page);
research.unlockFromGuide(this, p, profile, sfitem, player -> openItemGroup(profile, itemGroup, page));
return false;
});
} else {
Expand All @@ -305,9 +306,8 @@ private void displaySlimefunItem(ChestMenu menu, ItemGroup itemGroup, Player p,
Slimefun.getLocalization().sendMessage(pl, "guide.cheat.no-multiblocks");
} else {
ItemStack clonedItem = sfitem.getItem().clone();

if (action.isShiftClicked()) {
clonedItem.setAmount(clonedItem.getMaxStackSize());
clonedItem.setAmoutMaxStackSize();
WalshyDev marked this conversation as resolved.
Show resolved Hide resolved
}

pl.getInventory().addItem(clonedItem);
Expand All @@ -329,6 +329,23 @@ private void displaySlimefunItem(ChestMenu menu, ItemGroup itemGroup, Player p,
}
}

@ParametersAreNonnullByDefault
private @Nonnull ItemStack createLockedItem(Player p, SlimefunItem sfitem, Research research) {
SlimefunLocalization locale = Slimefun.getLocalization();

// @formatter:off
return new CustomItemStack(
ChestMenuUtils.getNotResearchedItem(),
"&f" + ItemUtils.getItemName(sfitem.getItem()),
"&4&l" + locale.getMessage(p, "guide.locked"),
"",
locale.getMessage(p, "guide.unlock.click"),
"",
locale.getMessage(p, "guide.unlock.cost").replace("%cost%", String.valueOf(research.getCost()))
);
// @formatter:on
}

@Override
@ParametersAreNonnullByDefault
public void openSearch(PlayerProfile profile, String input, boolean addToHistory) {
Expand Down Expand Up @@ -548,10 +565,23 @@ public void displayItem(PlayerProfile profile, SlimefunItem item, boolean addToH
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) -> {
MenuClickHandler clickHandler = (pl, slot, itemStack, action) -> {
try {
if (itemstack != null && itemstack.getType() != Material.BARRIER) {
displayItem(profile, itemstack, 0, true);
if (itemStack != null && itemStack.getType() != Material.BARRIER) {
displayItem(profile, itemStack, 0, true);
}
} catch (Exception | LinkageError x) {
printErrorMessage(pl, x);
}
return false;
};

MenuClickHandler lockedClickHandler = (pl, slot, itemStack, action) -> {
try {
SlimefunItem sfItem = SlimefunItem.getByItem(itemStack);

if (sfItem != null && sfItem.getResearch() != null) {
sfItem.getResearch().unlockFromGuide(this, p, profile, sfItem, player -> displayItem(profile, itemStack, 0, true));
}
} catch (Exception | LinkageError x) {
printErrorMessage(pl, x);
Expand All @@ -563,7 +593,9 @@ private void displayItem(ChestMenu menu, PlayerProfile profile, Player p, Object

for (int i = 0; i < 9; i++) {
ItemStack recipeItem = getDisplayItem(p, isSlimefunRecipe, recipe[i]);
menu.addItem(recipeSlots[i], recipeItem, clickHandler);
MenuClickHandler handler = (recipeItem instanceof UnlockableItemStack) ? lockedClickHandler : clickHandler;

menu.addItem(recipeSlots[i], recipeItem, handler);

if (recipeItem != null && item instanceof MultiBlockMachine) {
for (Tag<Material> tag : MultiBlock.getSupportedTags()) {
Expand Down Expand Up @@ -641,12 +673,18 @@ private void addBackButton(ChestMenu menu, int slot, Player p, PlayerProfile pro
if (isSlimefunRecipe) {
SlimefunItem slimefunItem = SlimefunItem.getByItem(item);

if (slimefunItem == null) {
if (slimefunItem == null || slimefunItem.canUse(p, false)) {
// Just return the item if it is usable or isn't a Slimefun item
return item;
}

String lore = hasPermission(p, slimefunItem) ? "&fNeeds to be unlocked in " + slimefunItem.getItemGroup().getDisplayName(p) : "&fNo Permission";
return slimefunItem.canUse(p, false) ? item : new CustomItemStack(Material.BARRIER, ItemUtils.getItemName(item), "&4&l" + Slimefun.getLocalization().getMessage(p, "guide.locked"), "", lore);
if (!Slimefun.getPermissionsService().hasPermission(p, slimefunItem)) {
return new CustomItemStack(Material.BARRIER, ItemUtils.getItemName(item), "&4&l" + Slimefun.getLocalization().getMessage(p, "guide.locked"), "", "&f" + Slimefun.getLocalization().getMessage(p, "guide.no-permission"));
} else if (!slimefunItem.getItem().hasItemMeta()) {
return new CustomItemStack(Material.BARRIER, ItemUtils.getItemName(item));
} else {
return new UnlockableItemStack(slimefunItem, p);
}
} else {
return item;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package io.github.thebusybiscuit.slimefun4.implementation.guide;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.ParametersAreNonnullByDefault;

import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.meta.ItemMeta;

import io.github.bakedlibs.dough.common.ChatColors;
import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack;
import io.github.thebusybiscuit.slimefun4.core.services.localization.SlimefunLocalization;
import io.github.thebusybiscuit.slimefun4.implementation.Slimefun;

/**
* An extension of {@link SlimefunItemStack} that indicates the item is unlockable in the guide.
* This is only used by {@link SurvivalSlimefunGuide}.
*
* @author RobotHanzo
*
* @see SurvivalSlimefunGuide
*/
class UnlockableItemStack extends SlimefunItemStack {
JustAHuman-xD marked this conversation as resolved.
Show resolved Hide resolved
J3fftw1 marked this conversation as resolved.
Show resolved Hide resolved

@ParametersAreNonnullByDefault
UnlockableItemStack(SlimefunItem item, Player p) {
super(item.getId(), item.getItem());

SlimefunLocalization locale = Slimefun.getLocalization();
ItemMeta meta = getItemMeta();
List<String> lore = new ArrayList<>();

lore.add(ChatColors.color("&4&l") + locale.getMessage(p, "guide.locked"));
lore.add("");
lore.add(ChatColors.color(locale.getMessage(p, "guide.unlock.click")));
lore.add("");
lore.add(ChatColors.color(locale.getMessage(p, "guide.unlock.cost").replace("%cost%", String.valueOf(item.getResearch().getCost()))));
meta.setLore(lore);

setItemMeta(meta);
setType(Material.BARRIER);
}
}
5 changes: 5 additions & 0 deletions src/main/resources/languages/en/messages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,13 @@ placeholderapi:

guide:
locked: 'LOCKED'
no-permission: 'No permission!'
work-in-progress: 'This feature is not fully finished yet!'

unlock:
click: '&a> Click to unlock'
cost: '&7Cost: &b%cost% XP level(s)'

locked-itemgroup:
- 'To unlock this category you will'
- 'need to unlock all items from the'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ void testPreCanUnlockResearchEvent() throws InterruptedException {
PlayerProfile profile = TestUtilities.awaitProfile(player);
SlimefunItem sfItem = TestUtilities.mockSlimefunItem(plugin, "RESEARCH_TEST", new CustomItemStack(Material.TORCH, "&bResearch Test"));

research.unlockFromGuide(guide, player, profile, sfItem, sfItem.getItemGroup(), 0);
research.unlockFromGuide(guide, player, profile, sfItem, ignored -> {});

server.getPluginManager().assertEventFired(PlayerPreResearchEvent.class, event -> {
Assertions.assertEquals(player, event.getPlayer());
Expand Down