Skip to content

Commit

Permalink
feat: add Vacuum enchantment
Browse files Browse the repository at this point in the history
closes #22
  • Loading branch information
RubixDev committed Nov 29, 2023
1 parent 6fa8e84 commit f3d2218
Show file tree
Hide file tree
Showing 11 changed files with 129 additions and 16 deletions.
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ from an enchanted container as long as the used stack was held in one of the
hands (see [configuration](#configuration)). Again, the container must be inside
your inventory.

### Vacuum

The Vacuum enchantment doesn't generate by default making it unobtainable in
survival. To change that, set the `generateVacuum` option to `true` (and
optionally disable Siphon by setting `generateSiphon` to `false`). Its behavior
is very similar to that of the Siphon enchantment, with the key difference that
it doesn't require the same item to already be present in the enchanted
container. This means a container enchanted with Vacuum will take all items you
pick up as long as it has space to do so.

## A note on Resource Packs

When using EnchantedShulkers with a resource pack that alters the look of
Expand Down Expand Up @@ -118,7 +128,10 @@ command in game. Below is a list of available options.
| `coloredNames` | `true`, `false` | `false` | Show the names of placed enchanted containers in aqua color. This applies to all players |
| `creativeSiphon` | `true`, `false` | `false` | Enable the Siphon enchantment for creative players |
| `creativeRefill` | `true`, `false` | `false` | Enable the Refill enchantment for creative players |
| `generateBooks` | `true`, `false` | `true` | Make the enchantments obtainable in survival by allowing enchanted books to generate with them |
| `creativeVacuum` | `true`, `false` | `false` | Enable the Vacuum enchantment for creative players |
| `generateSiphon` | `true`, `false` | `true` | Make the Siphon enchantment obtainable in survival by allowing enchanted books to generate with it |
| `generateRefill` | `true`, `false` | `true` | Make the Refill enchantment obtainable in survival by allowing enchanted books to generate with it |
| `generateVacuum` | `true`, `false` | `false` | Make the Vacuum enchantment obtainable in survival by allowing enchanted books to generate with it |
| `nestedContainers` | `true`, `false` | `true` | Search containers recursively up to 256 levels deep (e.g, search through Shulker Boxes in an Ender Chest) |

## For Mod Developers
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/de/rubixdev/enchantedshulkers/Mod.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import de.rubixdev.enchantedshulkers.config.WorldConfig;
import de.rubixdev.enchantedshulkers.enchantment.RefillEnchantment;
import de.rubixdev.enchantedshulkers.enchantment.SiphonEnchantment;
import de.rubixdev.enchantedshulkers.enchantment.VacuumEnchantment;
import de.rubixdev.enchantedshulkers.interfaces.HasClientMod;
import de.rubixdev.enchantedshulkers.interfaces.InventoryState;
import net.fabricmc.api.ModInitializer;
Expand Down Expand Up @@ -67,6 +68,7 @@ public class Mod implements ModInitializer {

public static final SiphonEnchantment SIPHON_ENCHANTMENT = new SiphonEnchantment();
public static final RefillEnchantment REFILL_ENCHANTMENT = new RefillEnchantment();
public static final VacuumEnchantment VACUUM_ENCHANTMENT = new VacuumEnchantment();

public static final Identifier CLIENT_INSTALLED_PACKET_ID = new Identifier(MOD_ID, "client_installed");
public static final Identifier INVENTORY_OPEN_PACKET_ID = new Identifier(MOD_ID, "inventory_open");
Expand All @@ -76,6 +78,7 @@ public class Mod implements ModInitializer {
public void onInitialize() {
Registry.register(Registries.ENCHANTMENT, new Identifier(MOD_ID, "siphon"), SIPHON_ENCHANTMENT);
Registry.register(Registries.ENCHANTMENT, new Identifier(MOD_ID, "refill"), REFILL_ENCHANTMENT);
Registry.register(Registries.ENCHANTMENT, new Identifier(MOD_ID, "vacuum"), VACUUM_ENCHANTMENT);

// Add enchanted_ender_chest data pack when enabled in config
FabricLoader.getInstance()
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/de/rubixdev/enchantedshulkers/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ private static List<ItemStack> getContainers(
List<ItemStack> inventory, ServerPlayerEntity player, Enchantment enchantment, int recursionDepth) {
List<ItemStack> out = new ArrayList<>();
for (ItemStack stack : inventory) {
// TODO: technically a vacuum shulker box inside a siphon ender chest should also be returned here,
// but unless someone complains i can't be bothered :P
if (canEnchant(stack)
&& EnchantmentHelper.getLevel(enchantment, stack) > 0
&& !(visitedEnderChest && stack.isOf(Items.ENDER_CHEST))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,20 @@ public static boolean creativeRefill() {
return inner.creativeRefill;
}

public static boolean generateBooks() {
return inner.generateBooks;
public static boolean creativeVacuum() {
return inner.creativeVacuum;
}

public static boolean generateRefill() {
return inner.generateRefill;
}

public static boolean generateSiphon() {
return inner.generateSiphon;
}

public static boolean generateVacuum() {
return inner.generateVacuum;
}

public static boolean nestedContainers() {
Expand All @@ -161,7 +173,10 @@ private static class Inner {
boolean coloredNames = false;
boolean creativeSiphon = false;
boolean creativeRefill = false;
boolean generateBooks = true;
boolean creativeVacuum = false;
boolean generateRefill = true;
boolean generateSiphon = true;
boolean generateVacuum = false;
boolean nestedContainers = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ public boolean isTreasure() {

@Override
public boolean isAvailableForEnchantedBookOffer() {
return WorldConfig.generateBooks();
return WorldConfig.generateRefill();
}

@Override
public boolean isAvailableForRandomSelection() {
return WorldConfig.generateBooks();
return WorldConfig.generateRefill();
}

public static void onPlayerTick(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,32 @@ public boolean isTreasure() {

@Override
public boolean isAvailableForEnchantedBookOffer() {
return WorldConfig.generateBooks();
return WorldConfig.generateSiphon();
}

@Override
public boolean isAvailableForRandomSelection() {
return WorldConfig.generateBooks();
return WorldConfig.generateSiphon();
}

public static boolean onItemPickup(ServerPlayerEntity player, ItemStack stack) {
if (player.isCreative() && !WorldConfig.creativeSiphon()) return false;
return onItemPickup(player, stack, Mod.SIPHON_ENCHANTMENT, true);
}

List<ItemStack> containerSlots = Utils.getContainers(player, Mod.SIPHON_ENCHANTMENT);
public static boolean onItemPickup(ServerPlayerEntity player, ItemStack stack, Enchantment enchantment, boolean requireStack) {
List<ItemStack> containerSlots = Utils.getContainers(player, enchantment);

boolean usedSiphon = false;
for (ItemStack container : containerSlots) {
if (stack.isEmpty()) return usedSiphon;
DefaultedList<ItemStack> containerInventory = Utils.getContainerInventory(container, player);

boolean updateContainer = false;
for (ItemStack innerStack : containerInventory) {
if (innerStack.isEmpty()) continue;
if (trySiphonStack(stack, innerStack)) {
for (int i = 0; i < containerInventory.toArray().length; i++) {
ItemStack innerStack = containerInventory.get(i);
if (innerStack.isEmpty() && requireStack) continue;
if (trySiphonStack(stack, innerStack, containerInventory, i)) {
updateContainer = true;
if (stack.isEmpty()) break;
}
Expand All @@ -68,7 +72,12 @@ public static boolean onItemPickup(ServerPlayerEntity player, ItemStack stack) {
return usedSiphon;
}

static boolean trySiphonStack(ItemStack from, ItemStack to) {
static boolean trySiphonStack(ItemStack from, ItemStack to, DefaultedList<ItemStack> containerInventory, int toIndex) {
if (to.isEmpty()) {
containerInventory.set(toIndex, from.copyAndEmpty());
return true;
}

if (!ItemStack.canCombine(from, to)) return false;
int transferCount = Math.min(to.getMaxCount() - to.getCount(), from.getCount());
if (transferCount <= 0) return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package de.rubixdev.enchantedshulkers.enchantment;

import de.rubixdev.enchantedshulkers.Mod;
import de.rubixdev.enchantedshulkers.Utils;
import de.rubixdev.enchantedshulkers.config.WorldConfig;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.collection.DefaultedList;

import java.util.List;

public class VacuumEnchantment extends Enchantment {
public VacuumEnchantment() {
super(Rarity.RARE, Mod.PORTABLE_CONTAINER_TARGET, new EquipmentSlot[] {
EquipmentSlot.MAINHAND, EquipmentSlot.OFFHAND
});
}

@Override
public int getMinPower(int level) {
return level * 25;
}

@Override
public int getMaxPower(int level) {
return getMinPower(level) + 50;
}

@Override
public boolean isTreasure() {
return true;
}

@Override
public boolean isAvailableForEnchantedBookOffer() {
return WorldConfig.generateVacuum();
}

@Override
public boolean isAvailableForRandomSelection() {
return WorldConfig.generateVacuum();
}

public static boolean onItemPickup(ServerPlayerEntity player, ItemStack stack) {
if (player.isCreative() && !WorldConfig.creativeVacuum()) return false;
return SiphonEnchantment.onItemPickup(player, stack, Mod.VACUUM_ENCHANTMENT, false);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.rubixdev.enchantedshulkers.mixin;

import de.rubixdev.enchantedshulkers.enchantment.SiphonEnchantment;
import de.rubixdev.enchantedshulkers.enchantment.VacuumEnchantment;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
Expand All @@ -23,6 +24,8 @@ public void insertStack(ItemStack stack, CallbackInfoReturnable<Boolean> cir) {
if (!(player instanceof ServerPlayerEntity serverPlayer)) return;
if (SiphonEnchantment.onItemPickup(serverPlayer, stack) && stack.isEmpty()) {
cir.setReturnValue(true);
} else if (VacuumEnchantment.onItemPickup(serverPlayer, stack) && stack.isEmpty()) {
cir.setReturnValue(true);
}
}
}
8 changes: 7 additions & 1 deletion src/main/resources/assets/enchantedshulkers/lang/de_de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ enchantment.enchantedshulkers:
refill: Nachfüllen
refill.desc: Gehaltene Gegenstände werden nach Benutzung automatisch nachgefüllt.

vacuum: Vakuum
vacuum.desc: Aufgesammelte Gegenstände werden gelagert wenn noch Platz ist.

commands.enchantedshulkers:
all_options_title: 'Alle EnchantedShulkers Einstellungen:'
current_value: 'Aktueller Wert: '
Expand All @@ -18,8 +21,11 @@ enchantedshulkers.options:
coloredNames.desc: Färbe die Namen von platzierten verzauberten Kisten aqua. Diese option ist global für alle Spieler.
creativeRefill.desc: Aktiviere die Nachfüllen Verzauberung für Spieler im Kreativmodus.
creativeSiphon.desc: Aktiviere die Saugen Verzauberung für Spieler im Kreativmodus.
creativeVacuum.desc: Aktiviere die Vakuum Verzauberung für Spieler im Kreativmodus.
enchantableEnderChest.desc: Endertruhen können auch verzaubert werden.
generateBooks.desc: Macht die Verzauberungen verfügbar im Überlebensmodus indem verzauberte Bücher mit diesen generieren können.
generateSiphon.desc: Macht die Saugen Verzauberung im Überlebensmodus verfügbar indem verzauberte Bücher mit ihr generieren können.
generateVacuum.desc: Macht die Vakuum Verzauberung im Überlebensmodus verfügbar indem verzauberte Bücher mit ihr generieren können.
generateRefill.desc: Macht die Nachfüllen Verzauberung im Überlebensmodus verfügbar indem verzauberte Bücher mit ihr generieren können.
nestedContainers.desc: Suche rekursiv in Kisten bis zu 256 Stufen tief (z.B. suche durch Schulker-Kisten die sich in der Endertruhe befinden).
refillNonStackables.desc: Erlaube das Nachfüllen von nicht stapelbaren Gegenständen wie z.B. Totems der Unsterblichkeit.
refillOffhand.desc: Erlaube das Nachfüllen von Stapeln in der Zweithand.
Expand Down
8 changes: 7 additions & 1 deletion src/main/resources/assets/enchantedshulkers/lang/en_us.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ enchantment.enchantedshulkers:
refill: Refill
refill.desc: Refills your held item from its inventory after use.

vacuum: Vacuum
vacuum.desc: Picked up items go in the storage if they fit anywhere.

commands.enchantedshulkers:
all_options_title: 'All EnchantedShulkers options:'
current_value: 'Current value: '
Expand All @@ -18,8 +21,11 @@ enchantedshulkers.options:
coloredNames.desc: Show the names of placed enchanted containers in aqua color. This applies to all players.
creativeRefill.desc: Enable the Refill enchantment for creative players.
creativeSiphon.desc: Enable the Siphon enchantment for creative players.
creativeVacuum.desc: Enable the Vacuum enchantment for creative players.
enchantableEnderChest.desc: Allows Ender Chests to also be enchanted.
generateBooks.desc: Make the enchantments obtainable in survival by allowing enchanted books to generate with them.
generateSiphon.desc: Make the Siphon enchantment obtainable in survival by allowing enchanted books to generate with it.
generateVacuum.desc: Make the Vacuum enchantment obtainable in survival by allowing enchanted books to generate with it.
generateRefill.desc: Make the Refill enchantment obtainable in survival by allowing enchanted books to generate with it.
nestedContainers.desc: Search containers recursively up to 256 levels deep (e.g, search through Shulker Boxes in an Ender Chest).
refillNonStackables.desc: Allow refilling non-stackable items like Totems of Undying.
refillOffhand.desc: Allow refilling stacks in the offhand.
Expand Down
8 changes: 7 additions & 1 deletion src/main/resources/assets/enchantedshulkers/lang/zh_cn.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ enchantment.enchantedshulkers:
refill: 补充
refill.desc: 手上的物品用完时,背包中的潜影盒内如果有相同的物品,就将之自动补充到手里

# vacuum: Vacuum
# vacuum.desc: Picked up items go in the storage if they fit anywhere.

commands.enchantedshulkers:
# all_options_title: 'All EnchantedShulkers options:'
# current_value: 'Current value: '
Expand All @@ -18,8 +21,11 @@ enchantedshulkers.options:
# coloredNames.desc: Show the names of placed enchanted containers in aqua color. This applies to all players.
# creativeRefill.desc: Enable the Refill enchantment for creative players.
# creativeSiphon.desc: Enable the Siphon enchantment for creative players.
# creativeVacuum.desc: Enable the Vacuum enchantment for creative players.
# enchantableEnderChest.desc: Allows Ender Chests to also be enchanted.
# generateBooks.desc: Make the enchantments obtainable in survival by allowing enchanted books to generate with them.
# generateSiphon.desc: Make the Siphon enchantment obtainable in survival by allowing enchanted books to generate with it.
# generateVacuum.desc: Make the Vacuum enchantment obtainable in survival by allowing enchanted books to generate with it.
# generateRefill.desc: Make the Refill enchantment obtainable in survival by allowing enchanted books to generate with it.
# nestedContainers.desc: Search containers recursively up to 256 levels deep (e.g, search through Shulker Boxes in an Ender Chest).
# refillNonStackables.desc: Allow refilling non-stackable items like Totems of Undying.
# refillOffhand.desc: Allow refilling stacks in the offhand.
Expand Down

0 comments on commit f3d2218

Please sign in to comment.