-
Notifications
You must be signed in to change notification settings - Fork 4
Implement GemKnife #36
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
Draft
cpaca
wants to merge
34
commits into
TraceLTRC:master
Choose a base branch
from
cpaca:LibraryOfMemories
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 27 commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
727082d
First library commit
cpaca 43de4a9
First attempt at writing shulkerForEach
cpaca 0c0d0db
Fix Library.java
cpaca a68b4cd
Switch Library to be an item instead of a book
cpaca dfbf867
Make shulker-box-abilities save when block broken
cpaca 1ea9dc9
Fix shulker-box-block-ability metadata
cpaca d632133
Fix Library onPlayerDeath for non-full shulkers
cpaca 4eec3bf
Move shulkerbox onBlockDropItem to its own thing
cpaca c86decb
Found the shulkerbox tag
cpaca 9d44b8b
Change shulkerForEach into editShulker
cpaca 8779c54
First GemKnife commit
cpaca c6e8959
Add things to relevant collections
cpaca 08b172b
Initial GemKnife implementation.
cpaca 3129c28
Fix gemknife emerald consumption
cpaca 76def6e
Update GemKnife to maybe use shulkerboxes
cpaca 8bc39cc
Merge branch 'master' into LibraryOfMemories
dlee13 8190f43
Revert changes to BlockAbility
dlee13 2fa284f
Refactor Library
dlee13 545775a
Revert changes to Util
dlee13 3537da5
Refactor LibraryBlock
dlee13 3abaf7a
Refactor GemKnife
dlee13 d0e7a9d
Rewrite Gem Knife
cpaca 94e75c6
Track remaining items instead of items-to-take
cpaca f6583b3
Attempt to make GemKnife work on Shulkers
cpaca 6539272
Fix GemKnife shulker check
cpaca edee0c1
Fix Library's onBlockDropItem
cpaca 428eaf8
Fix library momentos getting consumed
cpaca 1c4cccd
Optimize Library
cpaca 295b9ad
Merge branch 'master' into LibraryOfMemories
cpaca a245105
Implement Battery
dlee13 ae9f344
Refactor GemKnife
dlee13 9402a03
Require Battery to be in hotbar
dlee13 aa31934
Rename variable
dlee13 ac6d1ef
Remove unused superinterface
dlee13 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
213 changes: 213 additions & 0 deletions
213
src/main/java/xyz/holocons/mc/holoitemsrevamp/enchantment/GemKnife.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,213 @@ | ||
| package xyz.holocons.mc.holoitemsrevamp.enchantment; | ||
|
|
||
| import java.util.Map; | ||
| import java.util.concurrent.atomic.AtomicInteger; | ||
| import java.util.function.Function; | ||
| import java.util.function.Predicate; | ||
|
|
||
| import com.sk89q.worldedit.blocks.Blocks; | ||
| import org.bukkit.Material; | ||
| import org.bukkit.block.ShulkerBox; | ||
| import org.bukkit.enchantments.Enchantment; | ||
| import org.bukkit.event.player.PlayerInteractEvent; | ||
| import org.bukkit.inventory.Inventory; | ||
| import org.bukkit.inventory.ItemStack; | ||
| import org.bukkit.inventory.meta.BlockStateMeta; | ||
| import org.bukkit.util.Consumer; | ||
| import org.jetbrains.annotations.NotNull; | ||
|
|
||
| import com.destroystokyo.paper.MaterialTags; | ||
| import com.strangeone101.holoitemsapi.enchantment.CustomEnchantment; | ||
| import com.strangeone101.holoitemsapi.enchantment.EnchantmentAbility; | ||
|
|
||
| import net.kyori.adventure.text.Component; | ||
| import net.kyori.adventure.text.format.NamedTextColor; | ||
| import net.kyori.adventure.text.format.TextDecoration; | ||
| import xyz.holocons.mc.holoitemsrevamp.HoloItemsRevamp; | ||
|
|
||
| public class GemKnife extends CustomEnchantment implements EnchantmentAbility { | ||
|
|
||
| /** | ||
| * When you GemKnife a Block, what item will get spit out/output? | ||
| */ | ||
| private static final Map<Material, Material> COMPATIBLE_MATERIALS = Map.ofEntries( | ||
| Map.entry(Material.COAL_ORE, Material.COAL_BLOCK), | ||
| Map.entry(Material.DEEPSLATE_COAL_ORE, Material.COAL_BLOCK), | ||
| Map.entry(Material.IRON_ORE, Material.IRON_BLOCK), | ||
| Map.entry(Material.DEEPSLATE_IRON_ORE, Material.IRON_BLOCK), | ||
| Map.entry(Material.GOLD_ORE, Material.GOLD_BLOCK), | ||
| Map.entry(Material.DEEPSLATE_GOLD_ORE, Material.GOLD_BLOCK), | ||
| Map.entry(Material.NETHER_GOLD_ORE, Material.GOLD_BLOCK), | ||
| Map.entry(Material.GILDED_BLACKSTONE, Material.GOLD_BLOCK), | ||
| Map.entry(Material.REDSTONE_ORE, Material.REDSTONE_BLOCK), | ||
| Map.entry(Material.DEEPSLATE_REDSTONE_ORE, Material.REDSTONE_BLOCK), | ||
| Map.entry(Material.LAPIS_ORE, Material.LAPIS_BLOCK), | ||
| Map.entry(Material.DEEPSLATE_LAPIS_ORE, Material.LAPIS_BLOCK), | ||
| Map.entry(Material.NETHER_QUARTZ_ORE, Material.QUARTZ_BLOCK), | ||
| Map.entry(Material.GLOWSTONE, Material.GLOWSTONE)); | ||
|
|
||
| /** | ||
| * How much of each material do you get per-netherite-ingot? | ||
| */ | ||
| private static final Map<Material, Integer> MATERIALS_PER_INGOT = Map.ofEntries( | ||
| Map.entry(Material.COAL_BLOCK, 64), | ||
| Map.entry(Material.IRON_BLOCK, 64), | ||
| Map.entry(Material.GOLD_BLOCK, 64), | ||
| Map.entry(Material.REDSTONE_BLOCK, 64), | ||
| Map.entry(Material.LAPIS_BLOCK, 64), | ||
| Map.entry(Material.QUARTZ_BLOCK, 64), | ||
| Map.entry(Material.GLOWSTONE, 64) | ||
| ); | ||
|
|
||
| public GemKnife(HoloItemsRevamp plugin) { | ||
| super(plugin, "gem_knife"); | ||
| } | ||
|
|
||
| @Override | ||
| public int getMaxLevel() { | ||
| return 1; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean conflictsWith(@NotNull Enchantment enchantment) { | ||
| return false; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean canEnchantItem(@NotNull ItemStack item) { | ||
| return item.getType() == Material.EMERALD; | ||
| } | ||
|
|
||
| @Override | ||
| public @NotNull Component displayName(int level) { | ||
| return Component.text("Gem Knife", NamedTextColor.GRAY) | ||
| .decoration(TextDecoration.ITALIC, false); | ||
| } | ||
|
|
||
| @Override | ||
| public int getCostMultiplier() { | ||
| // TODO: should this be infinity instead? | ||
| return 12; | ||
| } | ||
|
|
||
| @Override | ||
| public void onPlayerInteract(PlayerInteractEvent event, ItemStack itemStack) { | ||
| final var clickedBlock = event.getClickedBlock(); | ||
| if (clickedBlock == null) { | ||
| return; | ||
| } | ||
| final var materialToDrop = COMPATIBLE_MATERIALS.get(clickedBlock.getType()); | ||
| if (materialToDrop == null) { | ||
| return; | ||
| } | ||
| final var amountPerIngot = MATERIALS_PER_INGOT.get(materialToDrop); | ||
| if(amountPerIngot == null) { | ||
| // Shouldn't be possible, but just in case. | ||
| return; | ||
| } | ||
|
|
||
| final var ingotsTaken = removeFromInventory( | ||
| event.getPlayer().getInventory(), 1, Material.NETHERITE_INGOT); | ||
| final var amountToDrop = amountPerIngot * ingotsTaken; | ||
|
|
||
| clickedBlock.getWorld().dropItemNaturally(clickedBlock.getLocation(), | ||
| new ItemStack(materialToDrop, amountToDrop)); | ||
| } | ||
|
|
||
| /** | ||
| * Removes an item from an inventory. Will recursively check into shulker boxes. | ||
| * @param inventory The inventory to scan for an item | ||
| * @param maxToTake The maximum amount of the item to remove from the inventory | ||
| * @param materialToTake What kind of material should be searched for/taken | ||
| * @return How many of the item was successfully removed from the inventory | ||
| */ | ||
| private static int removeFromInventory(Inventory inventory, final int maxToTake, Material materialToTake) { | ||
| int amountToTake = maxToTake; | ||
|
|
||
| for(ItemStack stack : inventory.getContents()) { | ||
| if(stack == null || stack.isEmpty()) { | ||
| continue; | ||
| } | ||
|
|
||
| // TODO: Check for "Battery" HoloItem | ||
| // That, or getShulkerBoxInventory (renamed to getBatteryInventory?) should do that. | ||
| final var shulkerInv = getShulkerBoxInventory(stack); | ||
| if(shulkerInv != null) { | ||
| final var finalAmountToTake = amountToTake; | ||
| final var amountTakenFromShulker = editShulkerBoxInventoryWithReturn(stack, editableShulkerInv -> | ||
| removeFromInventory(editableShulkerInv, finalAmountToTake, materialToTake)); | ||
| if(amountTakenFromShulker != null) { | ||
| amountToTake -= amountTakenFromShulker; | ||
| } | ||
|
|
||
| if(amountToTake == 0) { | ||
| return maxToTake; | ||
| } | ||
| continue; | ||
| } | ||
|
|
||
| if(stack.getType() != materialToTake) { | ||
| continue; | ||
| } | ||
|
|
||
| final var stackSize = stack.getAmount(); | ||
| if(stackSize >= amountToTake) { | ||
| // This stack has enough items. | ||
| stack.setAmount(stackSize - amountToTake); | ||
| return maxToTake; | ||
| } | ||
| else { | ||
| // This stack does not have enough items; absorb the entire stack. | ||
| amountToTake -= stackSize; | ||
| stack.setType(Material.AIR); | ||
| } | ||
| } | ||
| return maxToTake - amountToTake; | ||
| } | ||
|
|
||
| /** | ||
| * Edit the inventory of a shulkerbox. After the consumer is called, | ||
| * the shulker's inventory is saved, including any edits made. | ||
| * | ||
| * @param itemStack The (possible) shulkerbox to edit | ||
| * @param action The action to perform on the shulker's inventory. | ||
| */ | ||
| private static void editShulkerBoxInventory(ItemStack itemStack, Consumer<Inventory> action) { | ||
| itemStack.editMeta(BlockStateMeta.class, blockStateMeta -> { | ||
| if (blockStateMeta.getBlockState() instanceof ShulkerBox shulkerBox) { | ||
| action.accept(shulkerBox.getInventory()); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Edit the inventory of a shulkerbox. After the consumer is called, | ||
| * the shulker's inventory is saved, including any edits made. | ||
| * | ||
| * @param itemStack The (possible) shulkerbox to edit | ||
| * @param action The action to perform on the shulker's inventory | ||
| * @return The return value of action, or null if the action was not called. | ||
| * @param <R> The return type of the function | ||
| */ | ||
| private static <R> R editShulkerBoxInventoryWithReturn(ItemStack itemStack, Function<Inventory, R> action) { | ||
| if(!(itemStack.getItemMeta() instanceof BlockStateMeta blockStateMeta)) { | ||
| return null; | ||
| } | ||
| if(!(blockStateMeta.getBlockState() instanceof ShulkerBox shulkerBox)) { | ||
| return null; | ||
| } | ||
| R returnValue = action.apply(shulkerBox.getInventory()); | ||
| blockStateMeta.setBlockState(shulkerBox); | ||
| itemStack.setItemMeta(blockStateMeta); | ||
| return returnValue; | ||
| } | ||
|
|
||
| private static Inventory getShulkerBoxInventory(final ItemStack itemStack) { | ||
| if (itemStack.getItemMeta() instanceof BlockStateMeta blockStateMeta | ||
| && blockStateMeta.getBlockState() instanceof ShulkerBox shulkerBox) { | ||
| return shulkerBox.getInventory(); | ||
| } else { | ||
| return null; | ||
| } | ||
| } | ||
| } |
76 changes: 76 additions & 0 deletions
76
src/main/java/xyz/holocons/mc/holoitemsrevamp/enchantment/Library.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| package xyz.holocons.mc.holoitemsrevamp.enchantment; | ||
|
|
||
| import org.bukkit.Material; | ||
| import org.bukkit.block.ShulkerBox; | ||
| import org.bukkit.enchantments.Enchantment; | ||
| import org.bukkit.event.entity.PlayerDeathEvent; | ||
| import org.bukkit.inventory.ItemStack; | ||
| import org.bukkit.inventory.meta.BlockStateMeta; | ||
| import org.jetbrains.annotations.NotNull; | ||
|
|
||
| import com.strangeone101.holoitemsapi.enchantment.CustomEnchantment; | ||
| import com.strangeone101.holoitemsapi.enchantment.EnchantmentAbility; | ||
|
|
||
| import net.kyori.adventure.text.Component; | ||
| import net.kyori.adventure.text.format.NamedTextColor; | ||
| import net.kyori.adventure.text.format.TextDecoration; | ||
| import xyz.holocons.mc.holoitemsrevamp.HoloItemsRevamp; | ||
|
|
||
| public class Library extends CustomEnchantment implements EnchantmentAbility { | ||
|
|
||
| public Library(HoloItemsRevamp plugin) { | ||
| super(plugin, "library_of_memories"); | ||
| } | ||
|
|
||
| @Override | ||
| public int getMaxLevel() { | ||
| return 1; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean conflictsWith(@NotNull Enchantment enchantment) { | ||
| return false; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean canEnchantItem(@NotNull ItemStack itemStack) { | ||
| // TODO: Other colors of shulkerbox | ||
| return itemStack.getType() == Material.SHULKER_BOX; | ||
| } | ||
|
|
||
| @Override | ||
| public @NotNull Component displayName(int i) { | ||
| return Component.text() | ||
| .color(NamedTextColor.GRAY) | ||
| .decoration(TextDecoration.ITALIC, false) | ||
| .append(Component.text("Library of Memories")) | ||
| .build(); | ||
| } | ||
|
|
||
| @Override | ||
| public int getCostMultiplier() { | ||
| return 39; | ||
| } | ||
|
|
||
| @Override | ||
| public void onPlayerDeath(PlayerDeathEvent event, ItemStack itemStack) { | ||
| if (!(itemStack.getItemMeta() instanceof BlockStateMeta blockStateMeta) | ||
| || !(blockStateMeta.getBlockState() instanceof ShulkerBox shulkerBox)) { | ||
| return; | ||
| } | ||
|
|
||
| for (final var inventoryItemStack : shulkerBox.getInventory()) { | ||
| if(inventoryItemStack == null) { | ||
| continue; | ||
| } | ||
| for (final var enchantment : inventoryItemStack.getEnchantments().keySet()) { | ||
| if (enchantment instanceof Memento memento) { | ||
| memento.onPlayerDeath(event, inventoryItemStack); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| blockStateMeta.setBlockState(shulkerBox); | ||
| itemStack.setItemMeta(blockStateMeta); | ||
| } | ||
| } | ||
60 changes: 60 additions & 0 deletions
60
src/main/java/xyz/holocons/mc/holoitemsrevamp/item/GemKnifeItem.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| package xyz.holocons.mc.holoitemsrevamp.item; | ||
|
|
||
| import com.strangeone101.holoitemsapi.enchantment.CustomEnchantment; | ||
| import com.strangeone101.holoitemsapi.enchantment.EnchantManager; | ||
| import com.strangeone101.holoitemsapi.enchantment.Enchantable; | ||
| import com.strangeone101.holoitemsapi.item.CustomItem; | ||
| import net.kyori.adventure.text.Component; | ||
| import net.kyori.adventure.text.format.NamedTextColor; | ||
| import org.bukkit.Bukkit; | ||
| import org.bukkit.Material; | ||
| import org.bukkit.enchantments.Enchantment; | ||
| import org.bukkit.inventory.ItemStack; | ||
| import org.bukkit.inventory.Recipe; | ||
| import org.jetbrains.annotations.NotNull; | ||
| import xyz.holocons.mc.holoitemsrevamp.HoloItemsRevamp; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public class GemKnifeItem extends CustomItem implements Enchantable { | ||
| private static final String name = "gem_knife"; | ||
| private static final Material material = Material.EMERALD; | ||
| private static final Component displayName = Component.text("Gem Knife", NamedTextColor.GREEN); | ||
| private static final List<Component> lore = List.of( | ||
| Component.text("Right click to consume a charge and break a piece off of an ore soft than emerald.") | ||
| ); | ||
|
|
||
| private final EnchantManager enchantManager; | ||
|
|
||
| public GemKnifeItem(HoloItemsRevamp plugin) { | ||
| super(plugin, name, material, displayName, lore); | ||
| this.enchantManager = plugin.getEnchantManager(); | ||
| this.register(); | ||
| } | ||
|
|
||
| @Override | ||
| protected Recipe getRecipe() { | ||
| // TODO | ||
| return null; | ||
| } | ||
|
|
||
| @Override | ||
| public @NotNull Enchantment getEnchantment() { | ||
| return CustomEnchantment.getByKey(getKey()); | ||
| } | ||
|
|
||
| @Override | ||
| public ItemStack applyEnchantment(ItemStack itemStack) { | ||
| var enchantedStack = itemStack.clone(); | ||
| var enchantedMeta = enchantedStack.hasItemMeta() ? enchantedStack.getItemMeta() : Bukkit.getItemFactory().getItemMeta(enchantedStack.getType()); | ||
|
|
||
| if (enchantedMeta.addEnchant(getEnchantment(), 1, false)) { | ||
| enchantedStack.setItemMeta(enchantedMeta); | ||
| enchantManager.removeCustomEnchantmentLore(enchantedStack); | ||
| enchantManager.applyCustomEnchantmentLore(enchantedStack); | ||
| return enchantedStack; | ||
| } else { | ||
| return null; | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.