initial commit for shared version repo of Batteries mod - currently supports 1.21.11 and 1.21.1 of NeoForge.

This commit is contained in:
trunksbomb
2026-03-22 14:18:55 -04:00
commit 8d86c883ae
247 changed files with 18315 additions and 0 deletions

6261
.gitignore vendored Normal file

File diff suppressed because it is too large Load Diff

24
LICENSE.txt Normal file
View File

@@ -0,0 +1,24 @@
MIT License
Copyright (c) 2023 NeoForged project
This license applies to the template files as supplied by github.com/NeoForged/MDK
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

117
README.md Normal file
View File

@@ -0,0 +1,117 @@
# Batteries
Batteries is a tech mod for Minecraft using NeoForge. It's a port of my old 1.16 Batteries mod, with some additional features.
The mod focuses on charging items in your inventory in a configurable way.
This mod was born out of frustration with having a "power-hungry" item that sucked up all battery charge, leaving other items in my inventory with no charge.
Instead, each battery in this mod lets you configure what and how it charges.
## Features
### Batteries
![Screenshot1.png](Screenshot1.png)
The mod adds a battery progression with multiple tiers:
- Basic Battery
- Advanced Battery
- Elite Battery
- Ultimate Battery
- Ender Battery
- Creative Battery
Batteries can be charged in your choice of the Charger (included in this mod) or any other mod's charger functionality.
Each battery can be configured to charge:
- hotbar items
- main inventory items
- worn armor and offhand items
- nearby machines
The battery GUI also supports:
- whitelist and blacklist mode: only charge the things you want to charge
- fair charging: don't let power-hungry items sap all your battery's energy; a battery configred with fair charging will charge items to equilibrium
Ender Batteries can be linked to an Ender Charger for remote charging while carried by the player.
### Chargers
![Screenshot4.png](Screenshot4.png)
The mod includes two charger blocks:
- Charger
- Ender Charger
The regular Charger accepts normal batteries and charges them from inserted power.
The Ender Charger accepts a linked Ender Battery and sends energy into that linked battery while the charger remains loaded and the Ender battery is in the player's inventory.
### Battery Block
![Screenshot3.png](Screenshot3.png)
The Battery Block is a placeable energy storage block.
It provides:
- internal energy storage
- a configurable sided I/O GUI
- charge-level visuals on the block face
- capacity upgrades by crafting with batteries or additional Battery Blocks
### Coal Generator
The Coal Generator is a simple starter power source.
It:
- burns any furnace fuel
- generates configurable energy per tick
- outputs energy on all sides
- accepts fuel through its GUI
- accepts fuel automation from item insertion via hoppers or other mods' item transport
### Battery-Powered Gear
![Screenshot2.png](Screenshot2.png)
The mod adds battery-powered variants of gear:
- Diamond sword and tools
- Diamond armor
- Shield
- Bow
Battery-powered items:
- Are crafted with their respective item + one or more batteries
- Can have their energy capacity upgraded by crafting with additional batteries at any time
- Use energy instead of durability
- Use configurable additional energy per enchantment
- Stop functioning if out of energy, but don't break
- otherwise function identically to their non-powered versions
Notably:
- Mending and Unbreaking don't do anything on enchanted battery-powered items
### Recipes and Upgrades
- When crafting batteries or battery-powered items, they retain the charge they had, if any
- Batteries can be combined to make a new battery with larger capacity
- Battery Blocks can be combined with other Battery Blocks or Batteries to make a new Battery Block with larger capacity
- Battery-powered gear can similarly be upgraded with more battery storage
- Any recipe that takes a Battery or Battery Block can take one or more of those items to grant more energy capacity
### Debug Commands
The mod includes a `/batteries` command for testing and development.
Current commands include:
- `/batteries charge held|hotbar|inventory|all [amount]`
- `/batteries drain held|hotbar|inventory|all [amount]`
- `/batteries kit`
`/batteries kit` places a chest in front of the player containing the vanilla materials and base gear needed to craft the mod content from scratch.

BIN
Screenshot1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
Screenshot2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
Screenshot3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
Screenshot4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 KiB

16
build.gradle Normal file
View File

@@ -0,0 +1,16 @@
allprojects {
group = providers.gradleProperty('mod_group_id').orElse('com.trunksbomb.batteries').get()
version = providers.gradleProperty('mod_version').orElse('1.0.0').get()
}
subprojects {
repositories {
mavenCentral()
}
}
tasks.register('buildAllVersions') {
group = 'build'
description = 'Builds all version-specific NeoForge modules.'
dependsOn(subprojects.findAll { it.name.startsWith('neoforge-') }.collect { "${it.path}:build" })
}

8
common/README.md Normal file
View File

@@ -0,0 +1,8 @@
# Common Sources
Place shared Java and resource files here as you begin supporting more than one NeoForge target.
- Java: `common/src/main/java`
- Resources: `common/src/main/resources`
The version-specific modules include these directories directly in their main source sets.

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,124 @@
package com.trunksbomb.batteries;
import java.util.List;
import net.neoforged.neoforge.common.ModConfigSpec;
public final class BatteriesConfig {
private static final ModConfigSpec.Builder BUILDER = new ModConfigSpec.Builder();
public static final ModConfigSpec.IntValue MACHINE_CHARGE_RANGE = BUILDER
.comment("Maximum block range for battery charging of nearby machines.")
.defineInRange("machineChargeRange", 5, 1, 32);
public static final ModConfigSpec.BooleanValue ENABLE_POWERED_WEAPONS = BUILDER
.comment("Whether battery-powered weapons such as swords, bows, and shields can be crafted and shown in the Batteries tab.")
.define("enablePoweredWeapons", true);
public static final ModConfigSpec.BooleanValue ENABLE_POWERED_TOOLS = BUILDER
.comment("Whether battery-powered tools such as pickaxes, axes, shovels, and hoes can be crafted and shown in the Batteries tab.")
.define("enablePoweredTools", true);
public static final ModConfigSpec.BooleanValue ENABLE_POWERED_ARMOR = BUILDER
.comment("Whether battery-powered armor can be crafted and shown in the Batteries tab.")
.define("enablePoweredArmor", true);
public static final ModConfigSpec.BooleanValue CHARGER_GENERATES_CREATIVE_POWER = BUILDER
.comment("If true, chargers generate their own power and fill inserted batteries without an external energy source.")
.define("chargerGeneratesCreativePower", false);
public static final ModConfigSpec.IntValue GENERATOR_ENERGY_PER_TICK = BUILDER
.comment("Energy produced per tick by the coal generator while it is actively burning fuel.")
.defineInRange("generatorEnergyPerTick", 1, 1, Integer.MAX_VALUE);
public static final ModConfigSpec.IntValue PICKAXE_ENERGY_PER_BLOCK = BUILDER
.comment("Energy used by the battery-powered pickaxe for each block broken.")
.defineInRange("pickaxeEnergyPerBlock", 100, 0, Integer.MAX_VALUE);
public static final ModConfigSpec.IntValue AXE_ENERGY_PER_BLOCK = BUILDER
.comment("Energy used by battery-powered axes for each block broken.")
.defineInRange("axeEnergyPerBlock", 100, 0, Integer.MAX_VALUE);
public static final ModConfigSpec.IntValue SHOVEL_ENERGY_PER_BLOCK = BUILDER
.comment("Energy used by battery-powered shovels for each block broken.")
.defineInRange("shovelEnergyPerBlock", 100, 0, Integer.MAX_VALUE);
public static final ModConfigSpec.IntValue HOE_ENERGY_PER_BLOCK = BUILDER
.comment("Energy used by battery-powered hoes for each block broken.")
.defineInRange("hoeEnergyPerBlock", 100, 0, Integer.MAX_VALUE);
public static final ModConfigSpec.IntValue SWORD_ENERGY_PER_HIT = BUILDER
.comment("Energy used by battery-powered swords for each successful hit.")
.defineInRange("swordEnergyPerHit", 100, 0, Integer.MAX_VALUE);
public static final ModConfigSpec.IntValue ARMOR_ENERGY_PER_DAMAGE = BUILDER
.comment("Energy used by powered armor for each point of incoming damage absorbed as durability wear.")
.defineInRange("armorEnergyPerDamage", 500, 0, Integer.MAX_VALUE);
public static final ModConfigSpec.IntValue SHIELD_ENERGY_PER_BLOCK = BUILDER
.comment("Energy used by the powered shield for each blocked hit or projectile.")
.defineInRange("shieldEnergyPerBlock", 1_000, 0, Integer.MAX_VALUE);
public static final ModConfigSpec.IntValue BOW_FULLY_CHARGED_SHOT_COST = BUILDER
.comment("Energy used by the powered bow for a fully charged shot.")
.defineInRange("bowFullyChargedShotCost", 1_000, 0, Integer.MAX_VALUE);
public static final ModConfigSpec.DoubleValue ENCHANTMENT_ENERGY_MULTIPLIER = BUILDER
.comment("Additional power multiplier applied per enchantment at full strength. A level-scaled fraction of this value is added for each enchantment. Default 0.5 means each max-level enchant adds half the base cost.")
.defineInRange("enchantmentEnergyMultiplier", 0.5D, 0.0D, 100.0D);
public static final ModConfigSpec.ConfigValue<List<? extends String>> ENCHANTMENT_ENERGY_MULTIPLIER_OVERRIDES = BUILDER
.comment("Optional per-enchantment overrides in the form namespace:id=multiplier, for example minecraft:efficiency=0.5")
.defineListAllowEmpty("enchantmentEnergyMultiplierOverrides", List.of(), value -> value instanceof String);
public static final ModConfigSpec SPEC = BUILDER.build();
private BatteriesConfig() {
}
public static int machineChargeRange() {
return MACHINE_CHARGE_RANGE.get();
}
public static boolean chargerGeneratesCreativePower() {
return CHARGER_GENERATES_CREATIVE_POWER.get();
}
public static int generatorEnergyPerTick() {
return GENERATOR_ENERGY_PER_TICK.get();
}
public static boolean poweredArmorEnabled() {
return ENABLE_POWERED_ARMOR.get();
}
public static boolean poweredToolsEnabled() {
return ENABLE_POWERED_TOOLS.get();
}
public static boolean poweredWeaponsEnabled() {
return ENABLE_POWERED_WEAPONS.get();
}
public static int armorEnergyPerDamage() { return ARMOR_ENERGY_PER_DAMAGE.get(); }
public static int axeEnergyPerBlock() { return AXE_ENERGY_PER_BLOCK.get(); }
public static float bowFullyChargedShotCost() { return BOW_FULLY_CHARGED_SHOT_COST.get(); }
public static int hoeEnergyPerBlock() { return HOE_ENERGY_PER_BLOCK.get(); }
public static int pickaxeEnergyPerBlock() { return PICKAXE_ENERGY_PER_BLOCK.get(); }
public static double poweredItemEnchantmentMultiplier(String enchantmentId) {
for (String entry : ENCHANTMENT_ENERGY_MULTIPLIER_OVERRIDES.get()) {
int separator = entry.indexOf('=');
if (separator <= 0) {
continue;
}
String configuredId = entry.substring(0, separator).trim();
if (!configuredId.equals(enchantmentId)) {
continue;
}
try {
return Double.parseDouble(entry.substring(separator + 1).trim());
} catch (NumberFormatException ignored) {
return ENCHANTMENT_ENERGY_MULTIPLIER.get();
}
}
return ENCHANTMENT_ENERGY_MULTIPLIER.get();
}
public static int shovelEnergyPerBlock() { return SHOVEL_ENERGY_PER_BLOCK.get(); }
public static int shieldEnergyPerBlock() { return SHIELD_ENERGY_PER_BLOCK.get(); }
public static int swordEnergyPerHit() { return SWORD_ENERGY_PER_HIT.get(); }
}

View File

@@ -0,0 +1,49 @@
package com.trunksbomb.batteries;
import com.trunksbomb.batteries.item.PoweredItem;
import com.trunksbomb.batteries.item.PoweredItemEnergy;
import net.minecraft.core.Holder;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.enchantment.ItemEnchantments;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.event.AnvilUpdateEvent;
@EventBusSubscriber(modid = Batteries.MODID)
public final class PoweredItemEvents {
private PoweredItemEvents() {
}
@SubscribeEvent
public static void onAnvilUpdate(AnvilUpdateEvent event) {
ItemStack left = event.getLeft();
if (!(left.getItem() instanceof PoweredItem)) {
return;
}
if (addsMending(left, event.getRight()) || addsMending(left, event.getOutput())) {
event.setCanceled(true);
}
}
private static boolean addsMending(ItemStack original, ItemStack updated) {
if (updated.isEmpty()) {
return false;
}
int originalLevel = getMendingLevel(original);
int updatedLevel = getMendingLevel(updated);
return updatedLevel > originalLevel;
}
private static int getMendingLevel(ItemStack stack) {
ItemEnchantments enchantments = stack.getTagEnchantments();
for (Holder<Enchantment> enchantment : enchantments.keySet()) {
if (PoweredItemEnergy.isMendingEnchantment(enchantment)) {
return enchantments.getLevel(enchantment);
}
}
return 0;
}
}

View File

@@ -0,0 +1,48 @@
package com.trunksbomb.batteries.block;
import net.minecraft.core.Direction;
public final class BatteryBlockData {
public static final Direction[] MENU_DIRECTIONS = new Direction[] {
Direction.UP, Direction.DOWN, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST
};
private BatteryBlockData() {
}
public static Direction directionForIndex(int index) {
return MENU_DIRECTIONS[index];
}
public static int chargeStage(int energy, int capacity) {
if (capacity <= 0 || energy <= 0) {
return 0;
}
float ratio = energy / (float) capacity;
if (ratio >= 0.99F) {
return 4;
}
if (ratio >= 0.74F) {
return 3;
}
if (ratio >= 0.49F) {
return 2;
}
if (ratio >= 0.24F) {
return 1;
}
return 0;
}
public enum SideMode {
INPUT,
OUTPUT,
BOTH,
NONE;
public SideMode next() {
return values()[(this.ordinal() + 1) % values().length];
}
}
}

View File

@@ -0,0 +1,49 @@
package com.trunksbomb.batteries.block;
import com.trunksbomb.batteries.item.BatteryItemData.Tier;
import net.minecraft.util.StringRepresentable;
import org.jspecify.annotations.NonNull;
public final class ChargerBlockData {
private ChargerBlockData() {
}
public static boolean canAcceptBattery(boolean enderCharger, Tier tier) {
if (enderCharger) {
return tier == Tier.ENDER;
}
return tier != Tier.ENDER;
}
public enum BatteryState implements StringRepresentable {
NONE("none"),
BASIC("basic"),
ADVANCED("advanced"),
ELITE("elite"),
ULTIMATE("ultimate"),
CREATIVE("creative"),
ENDER("ender");
private final String name;
BatteryState(String name) {
this.name = name;
}
public static BatteryState fromTier(Tier tier) {
return switch (tier) {
case BASIC -> BASIC;
case ADVANCED -> ADVANCED;
case ELITE -> ELITE;
case ULTIMATE -> ULTIMATE;
case CREATIVE -> CREATIVE;
case ENDER -> ENDER;
};
}
@Override
public @NonNull String getSerializedName() {
return this.name;
}
}
}

View File

@@ -0,0 +1,250 @@
package com.trunksbomb.batteries.command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.trunksbomb.batteries.item.BatteryItemData;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.ChestBlock;
import net.minecraft.world.level.block.entity.ChestBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.jspecify.annotations.Nullable;
public final class BatteryDebugCommands {
private BatteryDebugCommands() {
}
public static <H> void register(CommandDispatcher<CommandSourceStack> dispatcher, EnergyAdapter<H> adapter) {
dispatcher.register(Commands.literal("batteries")
.then(Commands.literal("kit")
.executes(context -> placeKitChest(context.getSource())))
.then(buildAction("charge", Operation.CHARGE, adapter))
.then(buildAction("drain", Operation.DRAIN, adapter)));
}
private static <H> ArgumentBuilder<CommandSourceStack, ?> buildAction(String name, Operation operation, EnergyAdapter<H> adapter) {
LiteralArgumentBuilder<CommandSourceStack> action = Commands.literal(name);
for (Scope scope : Scope.values()) {
action.then(Commands.literal(scope.argumentName)
.executes(context -> execute(context.getSource(), operation, scope, null, adapter))
.then(Commands.argument("amount", IntegerArgumentType.integer(0))
.executes(context -> execute(
context.getSource(),
operation,
scope,
IntegerArgumentType.getInteger(context, "amount"),
adapter))));
}
return action;
}
private static <H> int execute(CommandSourceStack source, Operation operation, Scope scope, @Nullable Integer amount, EnergyAdapter<H> adapter) throws com.mojang.brigadier.exceptions.CommandSyntaxException {
ServerPlayer player = source.getPlayerOrException();
Summary summary = apply(player, operation, scope, amount, adapter);
source.sendSuccess(() -> summary.message(operation, scope, amount), true);
return summary.totalChangedEnergy;
}
private static <H> Summary apply(ServerPlayer player, Operation operation, Scope scope, @Nullable Integer amount, EnergyAdapter<H> adapter) {
Summary summary = new Summary();
for (ItemStack stack : scope.stacks(player)) {
if (stack.isEmpty()) {
continue;
}
H handler = adapter.resolve(stack);
if (handler == null) {
continue;
}
int capacity = Math.max(0, adapter.capacity(handler));
if (capacity <= 0) {
continue;
}
summary.chargeableItems++;
int stored = Math.max(0, Math.min(adapter.stored(handler), capacity));
int changed = switch (operation) {
case CHARGE -> {
int requested = amount == null ? capacity - stored : Math.min(Math.max(0, amount), capacity - stored);
yield requested <= 0 ? 0 : Math.max(0, adapter.charge(handler, requested));
}
case DRAIN -> {
int requested = amount == null ? stored : Math.min(Math.max(0, amount), stored);
yield requested <= 0 ? 0 : Math.max(0, adapter.drain(handler, requested));
}
};
if (changed > 0) {
summary.changedItems++;
summary.totalChangedEnergy += changed;
}
}
return summary;
}
private static int placeKitChest(CommandSourceStack source) throws com.mojang.brigadier.exceptions.CommandSyntaxException {
ServerPlayer player = source.getPlayerOrException();
Direction direction = player.getDirection();
BlockPos chestPos = player.blockPosition().relative(direction);
BlockState chestState = Blocks.CHEST.defaultBlockState()
.setValue(ChestBlock.FACING, direction.getOpposite());
player.level().setBlockAndUpdate(chestPos, chestState);
if (!(player.level().getBlockEntity(chestPos) instanceof ChestBlockEntity chest)) {
source.sendFailure(Component.literal("Couldn't create the kit chest."));
return 0;
}
chest.clearContent();
List<ItemStack> kit = List.of(
new ItemStack(Items.REDSTONE, 64),
new ItemStack(Items.REDSTONE_BLOCK, 64),
new ItemStack(Items.GOLD_INGOT, 64),
new ItemStack(Items.GOLD_BLOCK, 32),
new ItemStack(Items.IRON_INGOT, 64),
new ItemStack(Items.IRON_BLOCK, 16),
new ItemStack(Items.WHITE_CONCRETE, 64),
new ItemStack(Items.OAK_LOG, 64),
new ItemStack(Items.FURNACE, 16),
new ItemStack(Items.DIAMOND, 64),
new ItemStack(Items.DIAMOND_BLOCK, 16),
new ItemStack(Items.END_STONE, 32),
new ItemStack(Items.ENDER_PEARL, 32),
new ItemStack(Items.DIAMOND_PICKAXE),
new ItemStack(Items.DIAMOND_AXE),
new ItemStack(Items.DIAMOND_SHOVEL),
new ItemStack(Items.DIAMOND_HOE),
new ItemStack(Items.DIAMOND_SWORD),
new ItemStack(Items.DIAMOND_HELMET),
new ItemStack(Items.DIAMOND_CHESTPLATE),
new ItemStack(Items.DIAMOND_LEGGINGS),
new ItemStack(Items.DIAMOND_BOOTS),
new ItemStack(Items.SHIELD),
new ItemStack(Items.BOW)
);
for (int i = 0; i < kit.size() && i < chest.getContainerSize(); i++) {
chest.setItem(i, kit.get(i).copy());
}
chest.setChanged();
source.sendSuccess(() -> Component.literal("Placed a Batteries kit chest at "
+ chestPos.getX() + ", " + chestPos.getY() + ", " + chestPos.getZ() + "."), true);
return 1;
}
private enum Operation {
CHARGE("Charged"),
DRAIN("Drained");
private final String pastTense;
Operation(String pastTense) {
this.pastTense = pastTense;
}
}
private enum Scope {
HELD("held") {
@Override
List<ItemStack> stacks(ServerPlayer player) {
List<ItemStack> stacks = new ArrayList<>(2);
stacks.add(player.getMainHandItem());
stacks.add(player.getOffhandItem());
return stacks;
}
},
HOTBAR("hotbar") {
@Override
List<ItemStack> stacks(ServerPlayer player) {
List<ItemStack> stacks = new ArrayList<>(9);
for (int i = 0; i < 9; i++) {
stacks.add(player.getInventory().getItem(i));
}
return stacks;
}
},
INVENTORY("inventory") {
@Override
List<ItemStack> stacks(ServerPlayer player) {
List<ItemStack> stacks = new ArrayList<>(27);
for (int i = 9; i < 36; i++) {
stacks.add(player.getInventory().getItem(i));
}
return stacks;
}
},
ALL("all") {
@Override
List<ItemStack> stacks(ServerPlayer player) {
List<ItemStack> stacks = new ArrayList<>(player.getInventory().getContainerSize());
for (int i = 0; i < player.getInventory().getContainerSize(); i++) {
stacks.add(player.getInventory().getItem(i));
}
return stacks;
}
};
private final String argumentName;
Scope(String argumentName) {
this.argumentName = argumentName;
}
abstract List<ItemStack> stacks(ServerPlayer player);
}
private static final class Summary {
private int chargeableItems;
private int changedItems;
private int totalChangedEnergy;
private Component message(Operation operation, Scope scope, @Nullable Integer amount) {
if (this.chargeableItems == 0) {
return Component.literal("No chargeable items found in " + scope.argumentName + ".");
}
String amountText = amount == null
? (operation == Operation.CHARGE ? "to full" : "to empty")
: "by " + BatteryItemData.formatCompactAmount(amount) + " E";
return Component.literal(operation.pastTense
+ " "
+ this.changedItems
+ " of "
+ this.chargeableItems
+ " chargeable item(s) in "
+ scope.argumentName
+ " "
+ amountText
+ " ("
+ BatteryItemData.formatCompactAmount(this.totalChangedEnergy)
+ " E total).");
}
}
public interface EnergyAdapter<H> {
@Nullable H resolve(ItemStack stack);
int stored(H handler);
int capacity(H handler);
int charge(H handler, int amount);
int drain(H handler, int amount);
}
}

View File

@@ -0,0 +1,97 @@
package com.trunksbomb.batteries.item;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.ItemStack;
import java.lang.reflect.Method;
import java.util.Optional;
public final class BatteryItemData {
private static final String ENERGY_KEY = "energy";
private BatteryItemData() {
}
public static int getStoredEnergy(ItemStack stack, Tier tier) {
if (tier == Tier.CREATIVE) {
return getEnergyCapacity(tier);
}
CompoundTag tag = stack.getOrDefault(DataComponents.CUSTOM_DATA, net.minecraft.world.item.component.CustomData.EMPTY).copyTag();
return Math.max(0, readInt(tag, ENERGY_KEY));
}
public static void setStoredEnergy(ItemStack stack, int energy) {
net.minecraft.world.item.component.CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> tag.putInt(ENERGY_KEY, Math.max(0, energy)));
}
public static int getEnergyCapacity(Tier tier) {
return switch (tier) {
case BASIC -> 100_000;
case ADVANCED -> 750_000;
case ELITE -> 2_000_000;
case ULTIMATE, ENDER -> 10_000_000;
case CREATIVE -> Integer.MAX_VALUE;
};
}
public static int getMaxTransfer(Tier tier) {
return tier == Tier.CREATIVE ? Integer.MAX_VALUE : EnergyTierHelper.transferRateForCapacity(getEnergyCapacity(tier));
}
public static String formatWithCommas(int amount) {
return String.format("%,d", amount);
}
public static String formatCompactAmount(int amount) {
if (amount < 10_000) {
return formatWithCommas(amount);
}
if (amount < 1_000_000) {
return abbreviateRounded(amount, 1_000, "K");
}
if (amount < 1_000_000_000) {
return abbreviateRounded(amount, 1_000_000, "M");
}
return formatWithCommas(amount);
}
private static String abbreviateRounded(int amount, int divisor, String suffix) {
return Math.round(amount / (float) divisor) + suffix;
}
@SuppressWarnings("unchecked")
private static int readInt(CompoundTag tag, String key) {
try {
Method getIntMethod = CompoundTag.class.getMethod("getInt", String.class);
Object value = getIntMethod.invoke(tag, key);
if (value instanceof Integer intValue) {
return intValue;
}
if (value instanceof Optional<?> optionalValue && optionalValue.orElse(null) instanceof Integer intValue) {
return intValue;
}
} catch (ReflectiveOperationException ignored) {
}
try {
Method getIntOrMethod = CompoundTag.class.getMethod("getIntOr", String.class, int.class);
Object value = getIntOrMethod.invoke(tag, key, 0);
if (value instanceof Integer intValue) {
return intValue;
}
} catch (ReflectiveOperationException ignored) {
}
return 0;
}
public enum Tier {
BASIC,
ADVANCED,
ELITE,
ULTIMATE,
ENDER,
CREATIVE
}
}

View File

@@ -0,0 +1,86 @@
package com.trunksbomb.batteries.item;
import com.trunksbomb.batteries.BatteriesConfig;
import java.util.function.Consumer;
import net.minecraft.core.Holder;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.equipment.ArmorMaterial;
import net.minecraft.world.item.equipment.ArmorType;
import net.minecraft.world.item.enchantment.Enchantment;
import org.jspecify.annotations.Nullable;
public class BatteryPoweredArmorItem extends Item implements PoweredItem {
private final ArmorType armorType;
public BatteryPoweredArmorItem(ArmorMaterial material, ArmorType armorType, Properties properties) {
super(properties.humanoidArmor(material, armorType).stacksTo(1));
this.armorType = armorType;
}
@Override
public boolean isBarVisible(ItemStack stack) {
return this.isEnergyBarVisible(stack);
}
@Override
public int getBarWidth(ItemStack stack) {
return this.getEnergyBarWidth(stack);
}
@Override
public int getBarColor(ItemStack stack) {
return this.getEnergyBarColor(stack);
}
@Override
public void appendHoverText(ItemStack stack, TooltipContext context, net.minecraft.world.item.component.TooltipDisplay tooltipDisplay, Consumer<Component> tooltipAdder, TooltipFlag flag) {
this.addEnergyTooltip(stack, tooltipAdder, flag);
}
@Override
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
return this.shouldCauseEnergyReequipAnimation(oldStack, newStack, slotChanged);
}
@Override
public ItemStack getEnchantingBaseStack(ItemStack stack) {
return new ItemStack(switch (this.armorType) {
case HELMET -> Items.DIAMOND_HELMET;
case CHESTPLATE -> Items.DIAMOND_CHESTPLATE;
case LEGGINGS -> Items.DIAMOND_LEGGINGS;
case BOOTS -> Items.DIAMOND_BOOTS;
default -> Items.DIAMOND_CHESTPLATE;
});
}
@Override
public boolean supportsEnchantment(ItemStack stack, Holder<Enchantment> enchantment) {
return this.supportsPoweredEnchantment(stack, enchantment);
}
@Override
public boolean isPrimaryItemFor(ItemStack stack, Holder<Enchantment> enchantment) {
return this.isPrimaryPoweredItemFor(stack, enchantment);
}
@Override
public int getEnchantmentLevel(ItemStack stack, Holder<Enchantment> enchantment) {
return this.getPoweredEnchantmentLevel(stack, enchantment);
}
@Override
public float getXpRepairRatio(ItemStack stack) {
return this.getPoweredXpRepairRatio(stack);
}
@Override
public <T extends LivingEntity> int damageItem(ItemStack stack, int amount, @Nullable T entity, Consumer<Item> onBroken) {
int energyCost = this.getAdjustedEnergyCost(stack, amount * BatteriesConfig.armorEnergyPerDamage());
return PoweredItemEnergy.consumeEnergy(stack, energyCost) ? 0 : amount;
}
}

View File

@@ -0,0 +1,11 @@
package com.trunksbomb.batteries.item;
import com.trunksbomb.batteries.BatteriesConfig;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.ToolMaterial;
public class BatteryPoweredAxeItem extends BatteryPoweredMiningToolItem {
public BatteryPoweredAxeItem(Properties properties) {
super(Items.DIAMOND_AXE, properties.axe(ToolMaterial.DIAMOND, 5.0F, -3.0F), BatteriesConfig::axeEnergyPerBlock);
}
}

View File

@@ -0,0 +1,143 @@
package com.trunksbomb.batteries.item;
import com.trunksbomb.batteries.BatteriesConfig;
import java.util.List;
import java.util.function.Consumer;
import net.minecraft.core.Holder;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.stats.Stats;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BowItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.level.Level;
import org.jspecify.annotations.Nullable;
public class BatteryPoweredBowItem extends BowItem implements PoweredItem {
public BatteryPoweredBowItem(Properties properties) {
super(properties.stacksTo(1));
}
@Override
public boolean isBarVisible(ItemStack stack) {
return this.isEnergyBarVisible(stack);
}
@Override
public int getBarWidth(ItemStack stack) {
return this.getEnergyBarWidth(stack);
}
@Override
public int getBarColor(ItemStack stack) {
return this.getEnergyBarColor(stack);
}
@Override
public void appendHoverText(ItemStack stack, TooltipContext context, net.minecraft.world.item.component.TooltipDisplay tooltipDisplay, Consumer<Component> tooltipAdder, TooltipFlag flag) {
this.addEnergyTooltip(stack, tooltipAdder, flag);
}
@Override
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
return this.shouldCauseEnergyReequipAnimation(oldStack, newStack, slotChanged);
}
@Override
public ItemStack getEnchantingBaseStack(ItemStack stack) {
return new ItemStack(Items.BOW);
}
@Override
public boolean supportsEnchantment(ItemStack stack, Holder<Enchantment> enchantment) {
return this.supportsPoweredEnchantment(stack, enchantment);
}
@Override
public boolean isPrimaryItemFor(ItemStack stack, Holder<Enchantment> enchantment) {
return this.isPrimaryPoweredItemFor(stack, enchantment);
}
@Override
public int getEnchantmentLevel(ItemStack stack, Holder<Enchantment> enchantment) {
return this.getPoweredEnchantmentLevel(stack, enchantment);
}
@Override
public float getXpRepairRatio(ItemStack stack) {
return this.getPoweredXpRepairRatio(stack);
}
@Override
public InteractionResult use(Level level, Player player, InteractionHand usedHand) {
ItemStack stack = player.getItemInHand(usedHand);
if (!PoweredItemEnergy.hasEnergy(stack, 1)) {
return InteractionResult.FAIL;
}
return super.use(level, player, usedHand);
}
@Override
public boolean releaseUsing(ItemStack stack, Level level, LivingEntity livingEntity, int timeLeft) {
if (!(livingEntity instanceof Player player)) {
return false;
}
ItemStack projectile = player.getProjectile(stack);
if (projectile.isEmpty()) {
return false;
}
int charge = this.getUseDuration(stack, livingEntity) - timeLeft;
charge = net.neoforged.neoforge.event.EventHooks.onArrowLoose(stack, level, player, charge, !projectile.isEmpty());
if (charge < 0) {
return false;
}
float power = BowItem.getPowerForTime(charge);
if (power < 0.1F) {
return false;
}
int baseEnergyCost = Math.max(1, Math.round(BatteriesConfig.bowFullyChargedShotCost() * power));
int energyCost = this.getAdjustedEnergyCost(stack, baseEnergyCost);
if (!PoweredItemEnergy.hasEnergy(stack, energyCost)) {
return false;
}
List<ItemStack> projectiles = draw(stack, projectile, player);
if (level instanceof ServerLevel serverLevel && !projectiles.isEmpty()) {
if (!PoweredItemEnergy.consumeEnergy(stack, energyCost)) {
return false;
}
this.shoot(serverLevel, player, player.getUsedItemHand(), stack, projectiles, power * 3.0F, 1.0F, power == 1.0F, null);
}
level.playSound(
null,
player.getX(),
player.getY(),
player.getZ(),
SoundEvents.ARROW_SHOOT,
SoundSource.PLAYERS,
1.0F,
1.0F / (level.getRandom().nextFloat() * 0.4F + 1.2F) + power * 0.5F
);
player.awardStat(Stats.ITEM_USED.get(this));
return true;
}
@Override
public <T extends LivingEntity> int damageItem(ItemStack stack, int amount, @Nullable T entity, Consumer<Item> onBroken) {
return 0;
}
}

View File

@@ -0,0 +1,11 @@
package com.trunksbomb.batteries.item;
import com.trunksbomb.batteries.BatteriesConfig;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.ToolMaterial;
public class BatteryPoweredHoeItem extends BatteryPoweredMiningToolItem {
public BatteryPoweredHoeItem(Properties properties) {
super(Items.DIAMOND_HOE, properties.hoe(ToolMaterial.DIAMOND, -3.0F, 0.0F), BatteriesConfig::hoeEnergyPerBlock);
}
}

View File

@@ -0,0 +1,108 @@
package com.trunksbomb.batteries.item;
import java.util.function.Consumer;
import java.util.function.IntSupplier;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import org.jspecify.annotations.Nullable;
public abstract class BatteryPoweredMiningToolItem extends Item implements PoweredItem {
private final Item enchantingReferenceItem;
private final IntSupplier baseEnergyCostSupplier;
protected BatteryPoweredMiningToolItem(Item enchantingReferenceItem, Properties properties, IntSupplier baseEnergyCostSupplier) {
super(properties.stacksTo(1));
this.enchantingReferenceItem = enchantingReferenceItem;
this.baseEnergyCostSupplier = baseEnergyCostSupplier;
}
@Override
public boolean isBarVisible(ItemStack stack) {
return this.isEnergyBarVisible(stack);
}
@Override
public int getBarWidth(ItemStack stack) {
return this.getEnergyBarWidth(stack);
}
@Override
public int getBarColor(ItemStack stack) {
return this.getEnergyBarColor(stack);
}
@Override
public void appendHoverText(ItemStack stack, TooltipContext context, net.minecraft.world.item.component.TooltipDisplay tooltipDisplay, Consumer<Component> tooltipAdder, TooltipFlag flag) {
this.addEnergyTooltip(stack, tooltipAdder, flag);
}
@Override
public ItemStack getEnchantingBaseStack(ItemStack stack) {
return new ItemStack(this.enchantingReferenceItem);
}
@Override
public boolean supportsEnchantment(ItemStack stack, Holder<Enchantment> enchantment) {
return this.supportsPoweredEnchantment(stack, enchantment);
}
@Override
public boolean isPrimaryItemFor(ItemStack stack, Holder<Enchantment> enchantment) {
return this.isPrimaryPoweredItemFor(stack, enchantment);
}
@Override
public int getEnchantmentLevel(ItemStack stack, Holder<Enchantment> enchantment) {
return this.getPoweredEnchantmentLevel(stack, enchantment);
}
@Override
public float getXpRepairRatio(ItemStack stack) {
return this.getPoweredXpRepairRatio(stack);
}
@Override
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
return this.shouldCauseEnergyReequipAnimation(oldStack, newStack, slotChanged);
}
@Override
public boolean shouldCauseBlockBreakReset(ItemStack oldStack, ItemStack newStack) {
return this.shouldCauseEnergyBlockBreakReset(oldStack, newStack);
}
@Override
public float getDestroySpeed(ItemStack stack, BlockState state) {
return PoweredItemEnergy.hasEnergy(stack, this.energyCost(stack)) ? super.getDestroySpeed(stack, state) : 1.0F;
}
@Override
public boolean isCorrectToolForDrops(ItemStack stack, BlockState state) {
return PoweredItemEnergy.hasEnergy(stack, this.energyCost(stack)) && super.isCorrectToolForDrops(stack, state);
}
@Override
public boolean mineBlock(ItemStack stack, Level level, BlockState state, BlockPos pos, LivingEntity miningEntity) {
if (!level.isClientSide() && !state.isAir()) {
PoweredItemEnergy.consumeEnergy(stack, this.energyCost(stack));
}
return true;
}
@Override
public <T extends LivingEntity> int damageItem(ItemStack stack, int amount, @Nullable T entity, Consumer<Item> onBroken) {
return 0;
}
protected int energyCost(ItemStack stack) {
return this.getAdjustedEnergyCost(stack, this.baseEnergyCostSupplier.getAsInt());
}
}

View File

@@ -0,0 +1,11 @@
package com.trunksbomb.batteries.item;
import com.trunksbomb.batteries.BatteriesConfig;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.ToolMaterial;
public class BatteryPoweredPickaxeItem extends BatteryPoweredMiningToolItem {
public BatteryPoweredPickaxeItem(Properties properties) {
super(Items.DIAMOND_PICKAXE, properties.pickaxe(ToolMaterial.DIAMOND, 1.0F, -2.8F), BatteriesConfig::pickaxeEnergyPerBlock);
}
}

View File

@@ -0,0 +1,76 @@
package com.trunksbomb.batteries.item;
import com.trunksbomb.batteries.BatteriesConfig;
import java.util.function.Consumer;
import net.minecraft.core.Holder;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.ShieldItem;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.enchantment.Enchantment;
import org.jspecify.annotations.Nullable;
public class BatteryPoweredShieldItem extends ShieldItem implements PoweredItem {
public BatteryPoweredShieldItem(Properties properties) {
super(properties.stacksTo(1));
}
@Override
public boolean isBarVisible(ItemStack stack) {
return this.isEnergyBarVisible(stack);
}
@Override
public int getBarWidth(ItemStack stack) {
return this.getEnergyBarWidth(stack);
}
@Override
public int getBarColor(ItemStack stack) {
return this.getEnergyBarColor(stack);
}
@Override
public void appendHoverText(ItemStack stack, TooltipContext context, net.minecraft.world.item.component.TooltipDisplay tooltipDisplay, Consumer<Component> tooltipAdder, TooltipFlag flag) {
this.addEnergyTooltip(stack, tooltipAdder, flag);
}
@Override
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
return this.shouldCauseEnergyReequipAnimation(oldStack, newStack, slotChanged);
}
@Override
public ItemStack getEnchantingBaseStack(ItemStack stack) {
return new ItemStack(Items.SHIELD);
}
@Override
public boolean supportsEnchantment(ItemStack stack, Holder<Enchantment> enchantment) {
return this.supportsPoweredEnchantment(stack, enchantment);
}
@Override
public boolean isPrimaryItemFor(ItemStack stack, Holder<Enchantment> enchantment) {
return this.isPrimaryPoweredItemFor(stack, enchantment);
}
@Override
public int getEnchantmentLevel(ItemStack stack, Holder<Enchantment> enchantment) {
return this.getPoweredEnchantmentLevel(stack, enchantment);
}
@Override
public float getXpRepairRatio(ItemStack stack) {
return this.getPoweredXpRepairRatio(stack);
}
@Override
public <T extends LivingEntity> int damageItem(ItemStack stack, int amount, @Nullable T entity, Consumer<Item> onBroken) {
int energyCost = this.getAdjustedEnergyCost(stack, amount * BatteriesConfig.shieldEnergyPerBlock());
return PoweredItemEnergy.consumeEnergy(stack, energyCost) ? 0 : amount;
}
}

View File

@@ -0,0 +1,11 @@
package com.trunksbomb.batteries.item;
import com.trunksbomb.batteries.BatteriesConfig;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.ToolMaterial;
public class BatteryPoweredShovelItem extends BatteryPoweredMiningToolItem {
public BatteryPoweredShovelItem(Properties properties) {
super(Items.DIAMOND_SHOVEL, properties.shovel(ToolMaterial.DIAMOND, 1.5F, -3.0F), BatteriesConfig::shovelEnergyPerBlock);
}
}

View File

@@ -0,0 +1,93 @@
package com.trunksbomb.batteries.item;
import com.trunksbomb.batteries.BatteriesConfig;
import java.util.function.Consumer;
import net.minecraft.core.Holder;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.ToolMaterial;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.enchantment.Enchantment;
import org.jspecify.annotations.Nullable;
public class BatteryPoweredSwordItem extends Item implements PoweredItem {
public BatteryPoweredSwordItem(Properties properties) {
super(properties.sword(ToolMaterial.DIAMOND, 3.0F, -2.4F).stacksTo(1));
}
@Override
public boolean isBarVisible(ItemStack stack) {
return this.isEnergyBarVisible(stack);
}
@Override
public int getBarWidth(ItemStack stack) {
return this.getEnergyBarWidth(stack);
}
@Override
public int getBarColor(ItemStack stack) {
return this.getEnergyBarColor(stack);
}
@Override
public void appendHoverText(ItemStack stack, TooltipContext context, net.minecraft.world.item.component.TooltipDisplay tooltipDisplay, Consumer<Component> tooltipAdder, TooltipFlag flag) {
this.addEnergyTooltip(stack, tooltipAdder, flag);
}
@Override
public ItemStack getEnchantingBaseStack(ItemStack stack) {
return new ItemStack(Items.DIAMOND_SWORD);
}
@Override
public boolean supportsEnchantment(ItemStack stack, Holder<Enchantment> enchantment) {
return this.supportsPoweredEnchantment(stack, enchantment);
}
@Override
public boolean isPrimaryItemFor(ItemStack stack, Holder<Enchantment> enchantment) {
return this.isPrimaryPoweredItemFor(stack, enchantment);
}
@Override
public int getEnchantmentLevel(ItemStack stack, Holder<Enchantment> enchantment) {
return this.getPoweredEnchantmentLevel(stack, enchantment);
}
@Override
public float getXpRepairRatio(ItemStack stack) {
return this.getPoweredXpRepairRatio(stack);
}
@Override
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
return this.shouldCauseEnergyReequipAnimation(oldStack, newStack, slotChanged);
}
@Override
public boolean onLeftClickEntity(ItemStack stack, Player player, Entity entity) {
return !PoweredItemEnergy.hasEnergy(stack, this.energyCost(stack));
}
@Override
public void hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) {
if (!attacker.level().isClientSide()) {
PoweredItemEnergy.consumeEnergy(stack, this.energyCost(stack));
}
}
@Override
public <T extends LivingEntity> int damageItem(ItemStack stack, int amount, @Nullable T entity, Consumer<Item> onBroken) {
return 0;
}
private int energyCost(ItemStack stack) {
return this.getAdjustedEnergyCost(stack, BatteriesConfig.swordEnergyPerHit());
}
}

View File

@@ -0,0 +1,22 @@
package com.trunksbomb.batteries.item;
public final class EnergyTierHelper {
private EnergyTierHelper() {
}
public static int transferRateForCapacity(int capacity) {
if (capacity >= 10_000_000) {
return 5_000;
}
if (capacity >= 2_000_000) {
return 1_000;
}
if (capacity >= 750_000) {
return 300;
}
if (capacity >= 100_000) {
return 100;
}
return 50;
}
}

View File

@@ -0,0 +1,18 @@
package com.trunksbomb.batteries.item;
import net.minecraft.world.item.ItemStack;
import net.neoforged.neoforge.transfer.energy.SimpleEnergyHandler;
final class PoweredEnergyHandler extends SimpleEnergyHandler {
private final ItemStack stack;
PoweredEnergyHandler(ItemStack stack, int capacity, int maxTransfer, int energy) {
super(capacity, maxTransfer, maxTransfer, energy);
this.stack = stack;
}
@Override
protected void onEnergyChanged(int previousAmount) {
PoweredItemEnergy.setStoredEnergy(this.stack, this.energy);
}
}

View File

@@ -0,0 +1,86 @@
package com.trunksbomb.batteries.item;
import java.util.Optional;
import java.util.function.Consumer;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.enchantment.Enchantment;
import net.neoforged.neoforge.transfer.energy.EnergyHandler;
public interface PoweredItem {
default EnergyHandler createEnergyHandler(ItemStack stack) {
return PoweredItemEnergy.createEnergyHandler(stack, this.getMaxTransfer(stack));
}
default int getMaxTransfer(ItemStack stack) {
return EnergyTierHelper.transferRateForCapacity(PoweredItemEnergy.getEnergyCapacity(stack));
}
default boolean isEnergyBarVisible(ItemStack stack) {
return PoweredItemEnergy.getEnergyCapacity(stack) > 0;
}
default int getEnergyBarWidth(ItemStack stack) {
return PoweredItemEnergy.getBarWidth(stack);
}
default int getEnergyBarColor(ItemStack stack) {
return 0x55CC55;
}
default void addEnergyTooltip(ItemStack stack, Consumer<Component> tooltipAdder, TooltipFlag flag) {
PoweredItemEnergy.addEnergyTooltip(stack, tooltipAdder);
}
default ItemStack getEnchantingBaseStack(ItemStack stack) {
return stack;
}
default int getAdjustedEnergyCost(ItemStack stack, int baseCost) {
return PoweredItemEnergy.adjustEnergyCostForEnchantments(stack, baseCost);
}
default int getPoweredEnchantmentLevel(ItemStack stack, Holder<Enchantment> enchantment) {
if (PoweredItemEnergy.isDisabledPoweredItemEnchantment(enchantment)) {
return 0;
}
return stack.getTagEnchantments().getLevel(enchantment);
}
default float getPoweredXpRepairRatio(ItemStack stack) {
return 0.0F;
}
default boolean supportsPoweredEnchantment(ItemStack stack, Holder<Enchantment> enchantment) {
if (PoweredItemEnergy.isMendingEnchantment(enchantment)) {
return false;
}
ItemStack baseStack = this.getEnchantingBaseStack(stack);
return baseStack.is(Items.ENCHANTED_BOOK) || enchantment.value().isSupportedItem(baseStack);
}
default boolean isPrimaryPoweredItemFor(ItemStack stack, Holder<Enchantment> enchantment) {
ItemStack baseStack = this.getEnchantingBaseStack(stack);
if (baseStack.getItem() == Items.BOOK) {
return true;
}
Optional<HolderSet<Item>> primaryItems = enchantment.value().definition().primaryItems();
return this.supportsPoweredEnchantment(stack, enchantment) && (primaryItems.isEmpty() || baseStack.is(primaryItems.get()));
}
default boolean shouldCauseEnergyReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
return slotChanged || !newStack.is(oldStack.getItem());
}
default boolean shouldCauseEnergyBlockBreakReset(ItemStack oldStack, ItemStack newStack) {
return !newStack.is(oldStack.getItem());
}
}

View File

@@ -0,0 +1,171 @@
package com.trunksbomb.batteries.item;
import com.trunksbomb.batteries.BatteriesConfig;
import java.util.function.Consumer;
import net.minecraft.ChatFormatting;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.enchantment.Enchantment;
import net.minecraft.world.item.enchantment.ItemEnchantments;
import net.neoforged.neoforge.transfer.energy.EnergyHandler;
public final class PoweredItemEnergy {
private static final String ENERGY_KEY = "energy";
private static final String CAPACITY_KEY = "capacity";
public static final int DEFAULT_CAPACITY = 50_000;
private PoweredItemEnergy() {
}
public static EnergyHandler createEnergyHandler(ItemStack stack, int maxTransfer) {
if (!(stack.getItem() instanceof PoweredItem)) {
return null;
}
int capacity = getEnergyCapacity(stack);
return new PoweredEnergyHandler(stack, capacity, Math.max(1, maxTransfer), getStoredEnergy(stack));
}
public static int getStoredEnergy(ItemStack stack) {
CompoundTag tag = stack.getOrDefault(DataComponents.CUSTOM_DATA, net.minecraft.world.item.component.CustomData.EMPTY).copyTag();
return Math.max(0, tag.getIntOr(ENERGY_KEY, 0));
}
public static void setStoredEnergy(ItemStack stack, int energy) {
int capacity = getEnergyCapacity(stack);
int clamped = Math.max(0, Math.min(energy, capacity));
net.minecraft.world.item.component.CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> tag.putInt(ENERGY_KEY, clamped));
}
public static int getEnergyCapacity(ItemStack stack) {
CompoundTag tag = stack.getOrDefault(DataComponents.CUSTOM_DATA, net.minecraft.world.item.component.CustomData.EMPTY).copyTag();
int storedCapacity = Math.max(0, tag.getIntOr(CAPACITY_KEY, 0));
if (storedCapacity > 0) {
return storedCapacity;
}
return stack.getItem() instanceof PoweredItem ? DEFAULT_CAPACITY : 0;
}
public static void setEnergyCapacity(ItemStack stack, int capacity) {
int clampedCapacity = Math.max(0, capacity);
net.minecraft.world.item.component.CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> {
tag.putInt(CAPACITY_KEY, clampedCapacity);
tag.putInt(ENERGY_KEY, Math.max(0, Math.min(tag.getIntOr(ENERGY_KEY, 0), clampedCapacity)));
});
}
public static boolean hasEnergy(ItemStack stack, int amount) {
return amount <= 0 || getStoredEnergy(stack) >= amount;
}
public static boolean consumeEnergy(ItemStack stack, int amount) {
if (amount <= 0) {
return true;
}
int stored = getStoredEnergy(stack);
if (stored < amount) {
return false;
}
setStoredEnergy(stack, stored - amount);
return true;
}
public static int getBarWidth(ItemStack stack) {
int capacity = getEnergyCapacity(stack);
if (capacity <= 0) {
return 0;
}
return Math.round(13.0F * getStoredEnergy(stack) / (float) capacity);
}
public static void addEnergyTooltip(ItemStack stack, Consumer<Component> tooltipAdder) {
tooltipAdder.accept(Component.translatable("batteries.tooltip.energy", formatWithCommas(getStoredEnergy(stack)), abbreviateAmount(getEnergyCapacity(stack)))
.withStyle(ChatFormatting.GREEN));
}
public static int adjustEnergyCostForEnchantments(ItemStack stack, int baseCost) {
if (baseCost <= 0) {
return 0;
}
ItemEnchantments enchantments = stack.getTagEnchantments();
if (enchantments.keySet().isEmpty()) {
return baseCost;
}
double totalMultiplier = 1.0D;
for (Holder<Enchantment> enchantment : enchantments.keySet()) {
int level = enchantments.getLevel(enchantment);
if (level <= 0) {
continue;
}
int maxLevel = Math.max(1, enchantment.value().getMaxLevel());
double scaledLevel = Math.min(level, maxLevel) / (double) maxLevel;
String enchantmentId = enchantment.unwrapKey()
.map(key -> key.identifier().toString())
.orElse("");
totalMultiplier += BatteriesConfig.poweredItemEnchantmentMultiplier(enchantmentId) * scaledLevel;
}
return clampToInt(Math.max(1L, Math.round(baseCost * totalMultiplier)));
}
public static int clampToInt(long value) {
return (int) Math.max(0L, Math.min(Integer.MAX_VALUE, value));
}
public static boolean isMendingEnchantment(Holder<Enchantment> enchantment) {
return hasEnchantmentId(enchantment, "minecraft:mending");
}
public static boolean isDisabledPoweredItemEnchantment(Holder<Enchantment> enchantment) {
return hasEnchantmentId(enchantment, "minecraft:mending")
|| hasEnchantmentId(enchantment, "minecraft:unbreaking");
}
private static boolean hasEnchantmentId(Holder<Enchantment> enchantment, String id) {
return enchantment.unwrapKey()
.map(key -> id.equals(key.identifier().toString()))
.orElse(false);
}
public static String formatWithCommas(int amount) {
return String.format("%,d", amount);
}
public static String abbreviateAmount(int amount) {
if (amount >= 1_000_000_000) {
return abbreviate(amount, 1_000_000_000, "G");
}
if (amount >= 1_000_000) {
return abbreviate(amount, 1_000_000, "M");
}
if (amount >= 1_000) {
return abbreviate(amount, 1_000, "k");
}
return formatWithCommas(amount);
}
private static String abbreviate(int amount, int divisor, String suffix) {
int whole = amount / divisor;
int remainder = amount % divisor;
if (remainder == 0) {
return whole + suffix;
}
int decimal = (remainder * 10) / divisor;
if (decimal == 0) {
return whole + suffix;
}
return whole + "." + decimal + suffix;
}
}

View File

@@ -0,0 +1,48 @@
package com.trunksbomb.batteries.shared;
import net.minecraft.core.Direction;
public final class BatteryBlockData {
public static final Direction[] MENU_DIRECTIONS = new Direction[] {
Direction.UP, Direction.DOWN, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST
};
private BatteryBlockData() {
}
public static Direction directionForIndex(int index) {
return MENU_DIRECTIONS[index];
}
public static int chargeStage(int energy, int capacity) {
if (capacity <= 0 || energy <= 0) {
return 0;
}
float ratio = energy / (float) capacity;
if (ratio >= 0.99F) {
return 4;
}
if (ratio >= 0.74F) {
return 3;
}
if (ratio >= 0.49F) {
return 2;
}
if (ratio >= 0.24F) {
return 1;
}
return 0;
}
public enum SideMode {
INPUT,
OUTPUT,
BOTH,
NONE;
public SideMode next() {
return values()[(this.ordinal() + 1) % values().length];
}
}
}

View File

@@ -0,0 +1,49 @@
package com.trunksbomb.batteries.shared;
import com.trunksbomb.batteries.item.BatteryItemData.Tier;
import net.minecraft.util.StringRepresentable;
import org.jspecify.annotations.NonNull;
public final class ChargerBlockData {
private ChargerBlockData() {
}
public static boolean canAcceptBattery(boolean enderCharger, Tier tier) {
if (enderCharger) {
return tier == Tier.ENDER;
}
return tier != Tier.ENDER;
}
public enum BatteryState implements StringRepresentable {
NONE("none"),
BASIC("basic"),
ADVANCED("advanced"),
ELITE("elite"),
ULTIMATE("ultimate"),
CREATIVE("creative"),
ENDER("ender");
private final String name;
BatteryState(String name) {
this.name = name;
}
public static BatteryState fromTier(Tier tier) {
return switch (tier) {
case BASIC -> BASIC;
case ADVANCED -> ADVANCED;
case ELITE -> ELITE;
case ULTIMATE -> ULTIMATE;
case CREATIVE -> CREATIVE;
case ENDER -> ENDER;
};
}
@Override
public @NonNull String getSerializedName() {
return this.name;
}
}
}

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,24 @@
{
"variants": {
"charge=0,facing=north": { "model": "batteries:block/battery_block_0" },
"charge=0,facing=east": { "model": "batteries:block/battery_block_0", "y": 90 },
"charge=0,facing=south": { "model": "batteries:block/battery_block_0", "y": 180 },
"charge=0,facing=west": { "model": "batteries:block/battery_block_0", "y": 270 },
"charge=1,facing=north": { "model": "batteries:block/battery_block_1" },
"charge=1,facing=east": { "model": "batteries:block/battery_block_1", "y": 90 },
"charge=1,facing=south": { "model": "batteries:block/battery_block_1", "y": 180 },
"charge=1,facing=west": { "model": "batteries:block/battery_block_1", "y": 270 },
"charge=2,facing=north": { "model": "batteries:block/battery_block_2" },
"charge=2,facing=east": { "model": "batteries:block/battery_block_2", "y": 90 },
"charge=2,facing=south": { "model": "batteries:block/battery_block_2", "y": 180 },
"charge=2,facing=west": { "model": "batteries:block/battery_block_2", "y": 270 },
"charge=3,facing=north": { "model": "batteries:block/battery_block_3" },
"charge=3,facing=east": { "model": "batteries:block/battery_block_3", "y": 90 },
"charge=3,facing=south": { "model": "batteries:block/battery_block_3", "y": 180 },
"charge=3,facing=west": { "model": "batteries:block/battery_block_3", "y": 270 },
"charge=4,facing=north": { "model": "batteries:block/battery_block_4" },
"charge=4,facing=east": { "model": "batteries:block/battery_block_4", "y": 90 },
"charge=4,facing=south": { "model": "batteries:block/battery_block_4", "y": 180 },
"charge=4,facing=west": { "model": "batteries:block/battery_block_4", "y": 270 }
}
}

View File

@@ -0,0 +1,109 @@
{
"variants": {
"battery=none,facing=north": {
"model": "batteries:block/charger/charger_none"
},
"battery=basic,facing=north": {
"model": "batteries:block/charger/charger_basic"
},
"battery=advanced,facing=north": {
"model": "batteries:block/charger/charger_advanced"
},
"battery=elite,facing=north": {
"model": "batteries:block/charger/charger_elite"
},
"battery=ultimate,facing=north": {
"model": "batteries:block/charger/charger_ultimate"
},
"battery=creative,facing=north": {
"model": "batteries:block/charger/charger_creative"
},
"battery=ender,facing=north": {
"model": "batteries:block/charger/charger_ender"
},
"battery=none,facing=south": {
"model": "batteries:block/charger/charger_none",
"y": 180
},
"battery=basic,facing=south": {
"model": "batteries:block/charger/charger_basic",
"y": 180
},
"battery=advanced,facing=south": {
"model": "batteries:block/charger/charger_advanced",
"y": 180
},
"battery=elite,facing=south": {
"model": "batteries:block/charger/charger_elite",
"y": 180
},
"battery=ultimate,facing=south": {
"model": "batteries:block/charger/charger_ultimate",
"y": 180
},
"battery=creative,facing=south": {
"model": "batteries:block/charger/charger_creative",
"y": 180
},
"battery=ender,facing=south": {
"model": "batteries:block/charger/charger_ender",
"y": 180
},
"battery=none,facing=west": {
"model": "batteries:block/charger/charger_none",
"y": 270
},
"battery=basic,facing=west": {
"model": "batteries:block/charger/charger_basic",
"y": 270
},
"battery=advanced,facing=west": {
"model": "batteries:block/charger/charger_advanced",
"y": 270
},
"battery=elite,facing=west": {
"model": "batteries:block/charger/charger_elite",
"y": 270
},
"battery=ultimate,facing=west": {
"model": "batteries:block/charger/charger_ultimate",
"y": 270
},
"battery=creative,facing=west": {
"model": "batteries:block/charger/charger_creative",
"y": 270
},
"battery=ender,facing=west": {
"model": "batteries:block/charger/charger_ender",
"y": 270
},
"battery=none,facing=east": {
"model": "batteries:block/charger/charger_none",
"y": 90
},
"battery=basic,facing=east": {
"model": "batteries:block/charger/charger_basic",
"y": 90
},
"battery=advanced,facing=east": {
"model": "batteries:block/charger/charger_advanced",
"y": 90
},
"battery=elite,facing=east": {
"model": "batteries:block/charger/charger_elite",
"y": 90
},
"battery=ultimate,facing=east": {
"model": "batteries:block/charger/charger_ultimate",
"y": 90
},
"battery=creative,facing=east": {
"model": "batteries:block/charger/charger_creative",
"y": 90
},
"battery=ender,facing=east": {
"model": "batteries:block/charger/charger_ender",
"y": 90
}
}
}

View File

@@ -0,0 +1,12 @@
{
"variants": {
"facing=north,lit=false": { "model": "batteries:block/coal_generator" },
"facing=east,lit=false": { "model": "batteries:block/coal_generator", "y": 90 },
"facing=south,lit=false": { "model": "batteries:block/coal_generator", "y": 180 },
"facing=west,lit=false": { "model": "batteries:block/coal_generator", "y": 270 },
"facing=north,lit=true": { "model": "batteries:block/coal_generator_lit" },
"facing=east,lit=true": { "model": "batteries:block/coal_generator_lit", "y": 90 },
"facing=south,lit=true": { "model": "batteries:block/coal_generator_lit", "y": 180 },
"facing=west,lit=true": { "model": "batteries:block/coal_generator_lit", "y": 270 }
}
}

View File

@@ -0,0 +1,109 @@
{
"variants": {
"battery=none,facing=north": {
"model": "batteries:block/charger/ender_charger"
},
"battery=basic,facing=north": {
"model": "batteries:block/charger/ender_charger_full"
},
"battery=advanced,facing=north": {
"model": "batteries:block/charger/ender_charger_full"
},
"battery=elite,facing=north": {
"model": "batteries:block/charger/ender_charger_full"
},
"battery=ultimate,facing=north": {
"model": "batteries:block/charger/ender_charger_full"
},
"battery=creative,facing=north": {
"model": "batteries:block/charger/ender_charger_full"
},
"battery=ender,facing=north": {
"model": "batteries:block/charger/ender_charger_full"
},
"battery=none,facing=south": {
"model": "batteries:block/charger/ender_charger",
"y": 180
},
"battery=basic,facing=south": {
"model": "batteries:block/charger/ender_charger_full",
"y": 180
},
"battery=advanced,facing=south": {
"model": "batteries:block/charger/ender_charger_full",
"y": 180
},
"battery=elite,facing=south": {
"model": "batteries:block/charger/ender_charger_full",
"y": 180
},
"battery=ultimate,facing=south": {
"model": "batteries:block/charger/ender_charger_full",
"y": 180
},
"battery=creative,facing=south": {
"model": "batteries:block/charger/ender_charger_full",
"y": 180
},
"battery=ender,facing=south": {
"model": "batteries:block/charger/ender_charger_full",
"y": 180
},
"battery=none,facing=west": {
"model": "batteries:block/charger/ender_charger",
"y": 270
},
"battery=basic,facing=west": {
"model": "batteries:block/charger/ender_charger_full",
"y": 270
},
"battery=advanced,facing=west": {
"model": "batteries:block/charger/ender_charger_full",
"y": 270
},
"battery=elite,facing=west": {
"model": "batteries:block/charger/ender_charger_full",
"y": 270
},
"battery=ultimate,facing=west": {
"model": "batteries:block/charger/ender_charger_full",
"y": 270
},
"battery=creative,facing=west": {
"model": "batteries:block/charger/ender_charger_full",
"y": 270
},
"battery=ender,facing=west": {
"model": "batteries:block/charger/ender_charger_full",
"y": 270
},
"battery=none,facing=east": {
"model": "batteries:block/charger/ender_charger",
"y": 90
},
"battery=basic,facing=east": {
"model": "batteries:block/charger/ender_charger_full",
"y": 90
},
"battery=advanced,facing=east": {
"model": "batteries:block/charger/ender_charger_full",
"y": 90
},
"battery=elite,facing=east": {
"model": "batteries:block/charger/ender_charger_full",
"y": 90
},
"battery=ultimate,facing=east": {
"model": "batteries:block/charger/ender_charger_full",
"y": 90
},
"battery=creative,facing=east": {
"model": "batteries:block/charger/ender_charger_full",
"y": 90
},
"battery=ender,facing=east": {
"model": "batteries:block/charger/ender_charger_full",
"y": 90
}
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery1"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery2"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery3"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery_axe"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:block/battery_block_4"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery_boots"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery_bow"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery_chestplate"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery_creative"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery_ender"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery_helmet"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery_hoe"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery_leggings"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery_pickaxe"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery_shield"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery_shovel"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:item/battery_sword"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:block/charger/charger_none"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:block/coal_generator"
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "batteries:block/charger/ender_charger"
}
}

View File

@@ -0,0 +1,35 @@
{
"itemGroup.batteries": "Batteries",
"item.batteries.battery": "Basic Battery",
"item.batteries.battery1": "Advanced Battery",
"item.batteries.battery2": "Elite Battery",
"item.batteries.battery3": "Ultimate Battery",
"item.batteries.battery_ender": "Ender Battery",
"item.batteries.battery_creative": "Creative Battery",
"item.batteries.battery_pickaxe": "Battery-powered Pickaxe",
"item.batteries.battery_axe": "Battery-powered Axe",
"item.batteries.battery_shovel": "Battery-powered Shovel",
"item.batteries.battery_hoe": "Battery-powered Hoe",
"item.batteries.battery_sword": "Battery-powered Sword",
"item.batteries.battery_helmet": "Battery-powered Helmet",
"item.batteries.battery_chestplate": "Battery-powered Chestplate",
"item.batteries.battery_leggings": "Battery-powered Leggings",
"item.batteries.battery_boots": "Battery-powered Boots",
"item.batteries.battery_shield": "Battery-powered Shield",
"item.batteries.battery_bow": "Battery-powered Bow",
"item.batteries.battery_block": "Battery Block",
"block.batteries.coal_generator": "Coal Generator",
"block.batteries.battery_block": "Battery Block",
"block.batteries.charger": "Battery Charger",
"block.batteries.ender_charger": "Ender Battery Uplink",
"batteries.gui.button.whitelist": "Whitelist",
"batteries.gui.button.blacklist": "Blacklist",
"batteries.gui.button.charge_hotbar": "Charge Items on Hotbar",
"batteries.gui.button.charge_inventory": "Charge Items in Inventory",
"batteries.gui.button.charge_armor": "Charge Worn Items",
"batteries.gui.button.charge_fairly": "Charge items fairly",
"batteries.gui.button.charge_machine": "Charge nearby machines",
"container.batteries.battery_block": "Battery Block",
"container.batteries.coal_generator": "Coal Generator",
"batteries.tooltip.energy": "Energy: %s / %s"
}

View File

@@ -0,0 +1,12 @@
{
"parent": "minecraft:block/cube",
"textures": {
"particle": "batteries:block/battery_block_side",
"up": "batteries:block/battery_block_top",
"down": "batteries:block/battery_block_bottom",
"north": "batteries:block/battery_block_front_0",
"south": "batteries:block/battery_block_front_0",
"east": "batteries:block/battery_block_side",
"west": "batteries:block/battery_block_side"
}
}

View File

@@ -0,0 +1,12 @@
{
"parent": "minecraft:block/cube",
"textures": {
"particle": "batteries:block/battery_block_side",
"up": "batteries:block/battery_block_top",
"down": "batteries:block/battery_block_bottom",
"north": "batteries:block/battery_block_front_1",
"south": "batteries:block/battery_block_front_1",
"east": "batteries:block/battery_block_side",
"west": "batteries:block/battery_block_side"
}
}

View File

@@ -0,0 +1,12 @@
{
"parent": "minecraft:block/cube",
"textures": {
"particle": "batteries:block/battery_block_side",
"up": "batteries:block/battery_block_top",
"down": "batteries:block/battery_block_bottom",
"north": "batteries:block/battery_block_front_2",
"south": "batteries:block/battery_block_front_2",
"east": "batteries:block/battery_block_side",
"west": "batteries:block/battery_block_side"
}
}

View File

@@ -0,0 +1,12 @@
{
"parent": "minecraft:block/cube",
"textures": {
"particle": "batteries:block/battery_block_side",
"up": "batteries:block/battery_block_top",
"down": "batteries:block/battery_block_bottom",
"north": "batteries:block/battery_block_front_3",
"south": "batteries:block/battery_block_front_3",
"east": "batteries:block/battery_block_side",
"west": "batteries:block/battery_block_side"
}
}

View File

@@ -0,0 +1,12 @@
{
"parent": "minecraft:block/cube",
"textures": {
"particle": "batteries:block/battery_block_side",
"up": "batteries:block/battery_block_top",
"down": "batteries:block/battery_block_bottom",
"north": "batteries:block/battery_block_front_4",
"south": "batteries:block/battery_block_front_4",
"east": "batteries:block/battery_block_side",
"west": "batteries:block/battery_block_side"
}
}

View File

@@ -0,0 +1,12 @@
{
"parent": "minecraft:block/cube",
"textures": {
"particle": "batteries:block/charger/charger_top",
"down": "batteries:block/charger/charger_top",
"up": "batteries:block/charger/charger_top",
"north": "batteries:block/charger/charger_front",
"south": "batteries:block/charger/charger_front",
"west": "batteries:block/charger/charger_side",
"east": "batteries:block/charger/charger_side"
}
}

View File

@@ -0,0 +1,12 @@
{
"parent": "minecraft:block/cube",
"textures": {
"particle": "batteries:block/charger/charger_top",
"down": "batteries:block/charger/charger_top",
"up": "batteries:block/charger/charger_top",
"north": "batteries:block/charger/charger_advanced",
"south": "batteries:block/charger/charger_advanced",
"west": "batteries:block/charger/charger_side",
"east": "batteries:block/charger/charger_side"
}
}

View File

@@ -0,0 +1,12 @@
{
"parent": "minecraft:block/cube",
"textures": {
"particle": "batteries:block/charger/charger_top",
"down": "batteries:block/charger/charger_top",
"up": "batteries:block/charger/charger_top",
"north": "batteries:block/charger/charger_basic",
"south": "batteries:block/charger/charger_basic",
"west": "batteries:block/charger/charger_side",
"east": "batteries:block/charger/charger_side"
}
}

View File

@@ -0,0 +1,12 @@
{
"parent": "minecraft:block/cube",
"textures": {
"particle": "batteries:block/charger/charger_top",
"down": "batteries:block/charger/charger_top",
"up": "batteries:block/charger/charger_top",
"north": "batteries:block/charger/charger_creative",
"south": "batteries:block/charger/charger_creative",
"west": "batteries:block/charger/charger_side",
"east": "batteries:block/charger/charger_side"
}
}

View File

@@ -0,0 +1,12 @@
{
"parent": "minecraft:block/cube",
"textures": {
"particle": "batteries:block/charger/charger_top",
"down": "batteries:block/charger/charger_top",
"up": "batteries:block/charger/charger_top",
"north": "batteries:block/charger/charger_elite",
"south": "batteries:block/charger/charger_elite",
"west": "batteries:block/charger/charger_side",
"east": "batteries:block/charger/charger_side"
}
}

View File

@@ -0,0 +1,12 @@
{
"parent": "minecraft:block/cube",
"textures": {
"particle": "batteries:block/charger/charger_top",
"down": "batteries:block/charger/charger_top",
"up": "batteries:block/charger/charger_top",
"north": "batteries:block/charger/charger_ender",
"south": "batteries:block/charger/charger_ender",
"west": "batteries:block/charger/charger_side",
"east": "batteries:block/charger/charger_side"
}
}

View File

@@ -0,0 +1,12 @@
{
"parent": "minecraft:block/cube",
"textures": {
"particle": "batteries:block/charger/charger_top",
"down": "batteries:block/charger/charger_top",
"up": "batteries:block/charger/charger_top",
"north": "batteries:block/charger/charger_front",
"south": "batteries:block/charger/charger_front",
"west": "batteries:block/charger/charger_side",
"east": "batteries:block/charger/charger_side"
}
}

View File

@@ -0,0 +1,12 @@
{
"parent": "minecraft:block/cube",
"textures": {
"particle": "batteries:block/charger/charger_top",
"down": "batteries:block/charger/charger_top",
"up": "batteries:block/charger/charger_top",
"north": "batteries:block/charger/charger_ultimate",
"south": "batteries:block/charger/charger_ultimate",
"west": "batteries:block/charger/charger_side",
"east": "batteries:block/charger/charger_side"
}
}

View File

@@ -0,0 +1,9 @@
{
"parent": "batteries:block/charger/charger_none",
"textures": {
"north": "batteries:block/charger/charger_front",
"south": "batteries:block/charger/charger_front",
"up": "batteries:block/charger/ender_charger_top",
"down": "batteries:block/charger/ender_charger_top"
}
}

View File

@@ -0,0 +1,7 @@
{
"parent": "batteries:block/charger/ender_charger",
"textures": {
"north": "batteries:block/charger/charger_ender",
"south": "batteries:block/charger/charger_ender"
}
}

View File

@@ -0,0 +1,12 @@
{
"parent": "minecraft:block/cube",
"textures": {
"particle": "batteries:block/battery_block_side",
"up": "batteries:block/battery_block_top",
"down": "batteries:block/battery_block_bottom",
"north": "minecraft:block/furnace_front",
"south": "minecraft:block/furnace_front",
"east": "batteries:block/battery_block_side",
"west": "batteries:block/battery_block_side"
}
}

View File

@@ -0,0 +1,12 @@
{
"parent": "minecraft:block/cube",
"textures": {
"particle": "batteries:block/battery_block_side",
"up": "batteries:block/battery_block_top",
"down": "batteries:block/battery_block_bottom",
"north": "minecraft:block/furnace_front_on",
"south": "minecraft:block/furnace_front_on",
"east": "batteries:block/battery_block_side",
"west": "batteries:block/battery_block_side"
}
}

View File

@@ -0,0 +1,12 @@
{
"parent": "minecraft:block/cube",
"textures": {
"particle": "batteries:block/charger/ender_charger_top",
"down": "batteries:block/charger/ender_charger_top",
"up": "batteries:block/charger/ender_charger_top",
"north": "batteries:block/charger/charger_front",
"south": "batteries:block/charger/charger_front",
"west": "batteries:block/charger/charger_side",
"east": "batteries:block/charger/charger_side"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "batteries:item/battery"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "batteries:item/battery1"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "batteries:item/battery2"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "batteries:item/battery3"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "batteries:item/battery_axe"
}
}

View File

@@ -0,0 +1,3 @@
{
"parent": "batteries:block/battery_block_4"
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "batteries:item/battery_boots"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "batteries:item/battery_bow"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "batteries:item/battery_chestplate"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "batteries:item/battery_creative"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "batteries:item/battery_ender"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "batteries:item/battery_helmet"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "batteries:item/battery_hoe"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "batteries:item/battery_leggings"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "batteries:item/battery_pickaxe"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "batteries:item/battery_shield"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "batteries:item/battery_shovel"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "batteries:item/battery_sword"
}
}

View File

@@ -0,0 +1,3 @@
{
"parent": "batteries:block/charger/charger_none"
}

View File

@@ -0,0 +1,3 @@
{
"parent": "batteries:block/coal_generator"
}

View File

@@ -0,0 +1,3 @@
{
"parent": "batteries:block/charger/ender_charger"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 756 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Some files were not shown because too many files have changed in this diff Show More