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:
25
neoforge-1.21.1/build.gradle
Normal file
25
neoforge-1.21.1/build.gradle
Normal file
@@ -0,0 +1,25 @@
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'maven-publish'
|
||||
id 'net.neoforged.moddev' version '2.0.140'
|
||||
id 'idea'
|
||||
}
|
||||
|
||||
apply from: rootProject.file('gradle/neoforge-module.gradle')
|
||||
|
||||
sourceSets.main.java.srcDir(rootProject.file('neoforge-1.21.11/src/main/java'))
|
||||
sourceSets.main.java.exclude(
|
||||
'com/trunksbomb/batteries/Batteries.java',
|
||||
'com/trunksbomb/batteries/BatteriesClient.java',
|
||||
'com/trunksbomb/batteries/PoweredItemEvents.java',
|
||||
'com/trunksbomb/batteries/block/**',
|
||||
'com/trunksbomb/batteries/client/**',
|
||||
'com/trunksbomb/batteries/integration/**',
|
||||
'com/trunksbomb/batteries/item/BatteryPowered*.java',
|
||||
'com/trunksbomb/batteries/item/BatteryBlockItem.java',
|
||||
'com/trunksbomb/batteries/item/BatteryEnergyHandler.java',
|
||||
'com/trunksbomb/batteries/item/BatteryItem.java',
|
||||
'com/trunksbomb/batteries/item/Powered*.java',
|
||||
'com/trunksbomb/batteries/menu/**',
|
||||
'com/trunksbomb/batteries/recipe/**'
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.trunksbomb.batteries;
|
||||
|
||||
import com.trunksbomb.batteries.v21_1.client.screen.BatteryBlockScreen;
|
||||
import com.trunksbomb.batteries.v21_1.client.screen.BatteriesScreen;
|
||||
import com.trunksbomb.batteries.v21_1.client.screen.CoalGeneratorScreen;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.EventBusSubscriber;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent;
|
||||
|
||||
@Mod(value = BatteriesNeoForge121.MODID, dist = Dist.CLIENT)
|
||||
@EventBusSubscriber(modid = BatteriesNeoForge121.MODID, value = Dist.CLIENT)
|
||||
public class BatteriesClientNeoForge121 {
|
||||
@SubscribeEvent
|
||||
static void registerScreens(RegisterMenuScreensEvent event) {
|
||||
event.register(BatteriesNeoForge121.BATTERIES_MENU.get(), BatteriesScreen::new);
|
||||
event.register(BatteriesNeoForge121.BATTERY_BLOCK_MENU.get(), BatteryBlockScreen::new);
|
||||
event.register(BatteriesNeoForge121.COAL_GENERATOR_MENU.get(), CoalGeneratorScreen::new);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
package com.trunksbomb.batteries;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import com.trunksbomb.batteries.command.BatteryDebugCommands;
|
||||
import com.trunksbomb.batteries.item.BatteryItemData.Tier;
|
||||
import com.trunksbomb.batteries.v21_1.block.BatteryBlock;
|
||||
import com.trunksbomb.batteries.v21_1.block.ChargerBlock;
|
||||
import com.trunksbomb.batteries.v21_1.block.CoalGeneratorBlock;
|
||||
import com.trunksbomb.batteries.v21_1.block.entity.BatteryBlockEntity;
|
||||
import com.trunksbomb.batteries.v21_1.block.entity.ChargerBlockEntity;
|
||||
import com.trunksbomb.batteries.v21_1.block.entity.CoalGeneratorBlockEntity;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryBlockItem;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryItem;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryPoweredArmorItem;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryPoweredAxeItem;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryPoweredBowItem;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryPoweredHoeItem;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryPoweredPickaxeItem;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryPoweredShieldItem;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryPoweredShovelItem;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryPoweredSwordItem;
|
||||
import com.trunksbomb.batteries.v21_1.item.PoweredItem;
|
||||
import com.trunksbomb.batteries.v21_1.menu.BatteriesMenu;
|
||||
import com.trunksbomb.batteries.v21_1.menu.BatteryBlockMenu;
|
||||
import com.trunksbomb.batteries.v21_1.menu.CoalGeneratorMenu;
|
||||
import com.trunksbomb.batteries.v21_1.recipe.BatteryBlockUpgradeRecipe;
|
||||
import com.trunksbomb.batteries.v21_1.recipe.BatteryTierUpgradeRecipe;
|
||||
import com.trunksbomb.batteries.v21_1.recipe.PoweredGearUpgradeRecipe;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.item.ArmorItem;
|
||||
import net.minecraft.world.item.ArmorMaterials;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.CreativeModeTabs;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.CustomRecipe;
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.neoforged.bus.api.IEventBus;
|
||||
import net.neoforged.fml.ModContainer;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
import net.neoforged.fml.config.ModConfig;
|
||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
||||
import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent;
|
||||
import net.neoforged.neoforge.common.NeoForge;
|
||||
import net.neoforged.neoforge.common.extensions.IMenuTypeExtension;
|
||||
import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent;
|
||||
import net.neoforged.neoforge.event.RegisterCommandsEvent;
|
||||
import net.neoforged.neoforge.registries.DeferredBlock;
|
||||
import net.neoforged.neoforge.registries.DeferredHolder;
|
||||
import net.neoforged.neoforge.registries.DeferredItem;
|
||||
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@Mod(BatteriesNeoForge121.MODID)
|
||||
public class BatteriesNeoForge121 {
|
||||
public static final String MODID = "batteries";
|
||||
public static final Logger LOGGER = LogUtils.getLogger();
|
||||
public static final DeferredRegister.Blocks BLOCKS = DeferredRegister.createBlocks(MODID);
|
||||
public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(MODID);
|
||||
public static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITY_TYPES = DeferredRegister.create(Registries.BLOCK_ENTITY_TYPE, MODID);
|
||||
public static final DeferredRegister<MenuType<?>> MENU_TYPES = DeferredRegister.create(Registries.MENU, MODID);
|
||||
public static final DeferredRegister<CreativeModeTab> CREATIVE_MODE_TABS = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, MODID);
|
||||
public static final DeferredRegister<RecipeSerializer<?>> RECIPE_SERIALIZERS = DeferredRegister.create(Registries.RECIPE_SERIALIZER, MODID);
|
||||
|
||||
public static final DeferredItem<Item> BATTERY = registerBattery("battery", Tier.BASIC);
|
||||
public static final DeferredItem<Item> BATTERY1 = registerBattery("battery1", Tier.ADVANCED);
|
||||
public static final DeferredItem<Item> BATTERY2 = registerBattery("battery2", Tier.ELITE);
|
||||
public static final DeferredItem<Item> BATTERY3 = registerBattery("battery3", Tier.ULTIMATE);
|
||||
public static final DeferredItem<Item> BATTERY_ENDER = registerBattery("battery_ender", Tier.ENDER);
|
||||
public static final DeferredItem<Item> BATTERY_CREATIVE = registerBattery("battery_creative", Tier.CREATIVE);
|
||||
public static final DeferredItem<Item> BATTERY_PICKAXE = ITEMS.registerItem("battery_pickaxe", BatteryPoweredPickaxeItem::new, new Item.Properties().stacksTo(1));
|
||||
public static final DeferredItem<Item> BATTERY_AXE = ITEMS.registerItem("battery_axe", BatteryPoweredAxeItem::new, new Item.Properties().stacksTo(1));
|
||||
public static final DeferredItem<Item> BATTERY_SHOVEL = ITEMS.registerItem("battery_shovel", BatteryPoweredShovelItem::new, new Item.Properties().stacksTo(1));
|
||||
public static final DeferredItem<Item> BATTERY_HOE = ITEMS.registerItem("battery_hoe", BatteryPoweredHoeItem::new, new Item.Properties().stacksTo(1));
|
||||
public static final DeferredItem<Item> BATTERY_SWORD = ITEMS.registerItem("battery_sword", BatteryPoweredSwordItem::new, new Item.Properties().stacksTo(1));
|
||||
public static final DeferredItem<Item> BATTERY_HELMET = ITEMS.registerItem("battery_helmet",
|
||||
properties -> new BatteryPoweredArmorItem(ArmorMaterials.DIAMOND, ArmorItem.Type.HELMET, properties), new Item.Properties().stacksTo(1));
|
||||
public static final DeferredItem<Item> BATTERY_CHESTPLATE = ITEMS.registerItem("battery_chestplate",
|
||||
properties -> new BatteryPoweredArmorItem(ArmorMaterials.DIAMOND, ArmorItem.Type.CHESTPLATE, properties), new Item.Properties().stacksTo(1));
|
||||
public static final DeferredItem<Item> BATTERY_LEGGINGS = ITEMS.registerItem("battery_leggings",
|
||||
properties -> new BatteryPoweredArmorItem(ArmorMaterials.DIAMOND, ArmorItem.Type.LEGGINGS, properties), new Item.Properties().stacksTo(1));
|
||||
public static final DeferredItem<Item> BATTERY_BOOTS = ITEMS.registerItem("battery_boots",
|
||||
properties -> new BatteryPoweredArmorItem(ArmorMaterials.DIAMOND, ArmorItem.Type.BOOTS, properties), new Item.Properties().stacksTo(1));
|
||||
public static final DeferredItem<Item> BATTERY_SHIELD = ITEMS.registerItem("battery_shield", BatteryPoweredShieldItem::new, new Item.Properties().stacksTo(1));
|
||||
public static final DeferredItem<Item> BATTERY_BOW = ITEMS.registerItem("battery_bow", BatteryPoweredBowItem::new, new Item.Properties().stacksTo(1));
|
||||
public static final DeferredBlock<Block> BATTERY_BLOCK = BLOCKS.register("battery_block", id -> new BatteryBlock(BatteryBlock.batteryBlockProperties()));
|
||||
public static final DeferredBlock<Block> COAL_GENERATOR = BLOCKS.register("coal_generator", id -> new CoalGeneratorBlock(CoalGeneratorBlock.generatorProperties()));
|
||||
public static final DeferredBlock<Block> CHARGER = BLOCKS.register("charger", id -> new ChargerBlock(ChargerBlock.chargerProperties()));
|
||||
public static final DeferredBlock<Block> ENDER_CHARGER = BLOCKS.register("ender_charger", id -> new ChargerBlock(ChargerBlock.chargerProperties()));
|
||||
public static final DeferredItem<BlockItem> BATTERY_BLOCK_ITEM = ITEMS.register("battery_block",
|
||||
id -> new BatteryBlockItem(BATTERY_BLOCK.get(), new Item.Properties()));
|
||||
public static final DeferredItem<BlockItem> COAL_GENERATOR_ITEM = ITEMS.registerSimpleBlockItem("coal_generator", COAL_GENERATOR);
|
||||
public static final DeferredItem<BlockItem> CHARGER_ITEM = ITEMS.registerSimpleBlockItem("charger", CHARGER);
|
||||
public static final DeferredItem<BlockItem> ENDER_CHARGER_ITEM = ITEMS.registerSimpleBlockItem("ender_charger", ENDER_CHARGER);
|
||||
public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<BatteryBlockEntity>> BATTERY_BLOCK_ENTITY = BLOCK_ENTITY_TYPES.register("battery_block",
|
||||
id -> BlockEntityType.Builder.of(BatteryBlockEntity::new, BATTERY_BLOCK.get()).build(null));
|
||||
public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<CoalGeneratorBlockEntity>> COAL_GENERATOR_BLOCK_ENTITY = BLOCK_ENTITY_TYPES.register("coal_generator",
|
||||
id -> BlockEntityType.Builder.of(CoalGeneratorBlockEntity::new, COAL_GENERATOR.get()).build(null));
|
||||
public static final DeferredHolder<BlockEntityType<?>, BlockEntityType<ChargerBlockEntity>> CHARGER_BLOCK_ENTITY = BLOCK_ENTITY_TYPES.register("charger",
|
||||
id -> BlockEntityType.Builder.of(ChargerBlockEntity::new, CHARGER.get(), ENDER_CHARGER.get()).build(null));
|
||||
public static final DeferredHolder<MenuType<?>, MenuType<BatteriesMenu>> BATTERIES_MENU =
|
||||
MENU_TYPES.register("batteries_menu", () -> IMenuTypeExtension.create(BatteriesMenu::new));
|
||||
public static final DeferredHolder<MenuType<?>, MenuType<BatteryBlockMenu>> BATTERY_BLOCK_MENU =
|
||||
MENU_TYPES.register("battery_block_menu", () -> IMenuTypeExtension.create(BatteryBlockMenu::new));
|
||||
public static final DeferredHolder<MenuType<?>, MenuType<CoalGeneratorMenu>> COAL_GENERATOR_MENU =
|
||||
MENU_TYPES.register("coal_generator_menu", () -> IMenuTypeExtension.create(CoalGeneratorMenu::new));
|
||||
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<BatteryBlockUpgradeRecipe>> BATTERY_BLOCK_UPGRADE_RECIPE =
|
||||
RECIPE_SERIALIZERS.register("battery_block_upgrade", () -> new SimpleCraftingRecipeSerializer<>(BatteryBlockUpgradeRecipe::new));
|
||||
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<BatteryTierUpgradeRecipe>> BATTERY_TIER_UPGRADE_RECIPE =
|
||||
RECIPE_SERIALIZERS.register("battery_tier_upgrade", () -> new SimpleCraftingRecipeSerializer<>(BatteryTierUpgradeRecipe::new));
|
||||
public static final DeferredHolder<RecipeSerializer<?>, RecipeSerializer<PoweredGearUpgradeRecipe>> POWERED_GEAR_UPGRADE_RECIPE =
|
||||
RECIPE_SERIALIZERS.register("powered_gear_upgrade", () -> new SimpleCraftingRecipeSerializer<>(PoweredGearUpgradeRecipe::new));
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static final DeferredHolder<CreativeModeTab, CreativeModeTab> BATTERIES_TAB = CREATIVE_MODE_TABS.register("main", () -> CreativeModeTab.builder()
|
||||
.title(Component.translatable("itemGroup.batteries"))
|
||||
.withTabsBefore(CreativeModeTabs.REDSTONE_BLOCKS)
|
||||
.icon(() -> new ItemStack(BATTERY.get()))
|
||||
.displayItems((parameters, output) -> {
|
||||
output.accept(new ItemStack(BATTERY.get()));
|
||||
output.accept(new ItemStack(BATTERY1.get()));
|
||||
output.accept(new ItemStack(BATTERY2.get()));
|
||||
output.accept(new ItemStack(BATTERY3.get()));
|
||||
output.accept(new ItemStack(BATTERY_ENDER.get()));
|
||||
output.accept(new ItemStack(BATTERY_CREATIVE.get()));
|
||||
if (BatteriesConfig.poweredToolsEnabled()) {
|
||||
output.accept(new ItemStack(BATTERY_PICKAXE.get()));
|
||||
output.accept(new ItemStack(BATTERY_AXE.get()));
|
||||
output.accept(new ItemStack(BATTERY_SHOVEL.get()));
|
||||
output.accept(new ItemStack(BATTERY_HOE.get()));
|
||||
}
|
||||
if (BatteriesConfig.poweredWeaponsEnabled()) {
|
||||
output.accept(new ItemStack(BATTERY_SWORD.get()));
|
||||
output.accept(new ItemStack(BATTERY_SHIELD.get()));
|
||||
output.accept(new ItemStack(BATTERY_BOW.get()));
|
||||
}
|
||||
if (BatteriesConfig.poweredArmorEnabled()) {
|
||||
output.accept(new ItemStack(BATTERY_HELMET.get()));
|
||||
output.accept(new ItemStack(BATTERY_CHESTPLATE.get()));
|
||||
output.accept(new ItemStack(BATTERY_LEGGINGS.get()));
|
||||
output.accept(new ItemStack(BATTERY_BOOTS.get()));
|
||||
}
|
||||
output.accept(new ItemStack(BATTERY_BLOCK_ITEM.get()));
|
||||
output.accept(new ItemStack(COAL_GENERATOR_ITEM.get()));
|
||||
output.accept(new ItemStack(CHARGER_ITEM.get()));
|
||||
output.accept(new ItemStack(ENDER_CHARGER_ITEM.get()));
|
||||
})
|
||||
.build());
|
||||
|
||||
public BatteriesNeoForge121(IEventBus modEventBus, ModContainer modContainer) {
|
||||
BLOCKS.register(modEventBus);
|
||||
ITEMS.register(modEventBus);
|
||||
BLOCK_ENTITY_TYPES.register(modEventBus);
|
||||
MENU_TYPES.register(modEventBus);
|
||||
CREATIVE_MODE_TABS.register(modEventBus);
|
||||
RECIPE_SERIALIZERS.register(modEventBus);
|
||||
modEventBus.addListener(BatteriesNeoForge121::registerCapabilities);
|
||||
modEventBus.addListener(BatteriesNeoForge121::buildCreativeTabContents);
|
||||
NeoForge.EVENT_BUS.addListener(BatteriesNeoForge121::registerCommands);
|
||||
modContainer.registerConfig(ModConfig.Type.SERVER, BatteriesConfig.SPEC);
|
||||
LOGGER.info("Loading Batteries MVP for Minecraft 1.21.1");
|
||||
}
|
||||
|
||||
private static void registerCapabilities(RegisterCapabilitiesEvent event) {
|
||||
event.registerItem(Capabilities.EnergyStorage.ITEM, (stack, context) -> BatteryItem.createEnergyHandler(stack),
|
||||
BATTERY.get(), BATTERY1.get(), BATTERY2.get(), BATTERY3.get(), BATTERY_ENDER.get(), BATTERY_CREATIVE.get());
|
||||
event.registerItem(Capabilities.EnergyStorage.ITEM, (stack, context) -> stack.getItem() instanceof PoweredItem poweredItem ? poweredItem.createEnergyHandler(stack) : null,
|
||||
BATTERY_PICKAXE.get(), BATTERY_AXE.get(), BATTERY_SHOVEL.get(), BATTERY_HOE.get(), BATTERY_SWORD.get(),
|
||||
BATTERY_HELMET.get(), BATTERY_CHESTPLATE.get(), BATTERY_LEGGINGS.get(), BATTERY_BOOTS.get(), BATTERY_SHIELD.get(), BATTERY_BOW.get());
|
||||
event.registerItem(Capabilities.EnergyStorage.ITEM, (stack, context) -> BatteryBlockItem.createEnergyHandler(stack), BATTERY_BLOCK_ITEM.get());
|
||||
event.registerBlockEntity(Capabilities.EnergyStorage.BLOCK, BATTERY_BLOCK_ENTITY.get(), BatteryBlockEntity::getEnergyStorage);
|
||||
event.registerBlockEntity(Capabilities.EnergyStorage.BLOCK, COAL_GENERATOR_BLOCK_ENTITY.get(), CoalGeneratorBlockEntity::getEnergyStorage);
|
||||
event.registerBlockEntity(Capabilities.ItemHandler.BLOCK, COAL_GENERATOR_BLOCK_ENTITY.get(), CoalGeneratorBlockEntity::getItemHandler);
|
||||
event.registerBlockEntity(Capabilities.EnergyStorage.BLOCK, CHARGER_BLOCK_ENTITY.get(), ChargerBlockEntity::getEnergyStorage);
|
||||
}
|
||||
|
||||
private static void registerCommands(RegisterCommandsEvent event) {
|
||||
BatteryDebugCommands.register(event.getDispatcher(), new BatteryDebugCommands.EnergyAdapter<net.neoforged.neoforge.energy.IEnergyStorage>() {
|
||||
@Override
|
||||
public net.neoforged.neoforge.energy.IEnergyStorage resolve(ItemStack stack) {
|
||||
return stack.getCapability(Capabilities.EnergyStorage.ITEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int stored(net.neoforged.neoforge.energy.IEnergyStorage handler) {
|
||||
return handler.getEnergyStored();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int capacity(net.neoforged.neoforge.energy.IEnergyStorage handler) {
|
||||
return handler.getMaxEnergyStored();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int charge(net.neoforged.neoforge.energy.IEnergyStorage handler, int amount) {
|
||||
return handler.receiveEnergy(amount, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int drain(net.neoforged.neoforge.energy.IEnergyStorage handler, int amount) {
|
||||
return handler.extractEnergy(amount, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void buildCreativeTabContents(BuildCreativeModeTabContentsEvent event) {
|
||||
if (!event.getTabKey().equals(CreativeModeTabs.INGREDIENTS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.accept(new ItemStack(BATTERY.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
event.accept(new ItemStack(BATTERY1.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
event.accept(new ItemStack(BATTERY2.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
event.accept(new ItemStack(BATTERY3.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
event.accept(new ItemStack(BATTERY_ENDER.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
event.accept(new ItemStack(BATTERY_CREATIVE.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
if (BatteriesConfig.poweredToolsEnabled()) {
|
||||
event.accept(new ItemStack(BATTERY_PICKAXE.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
event.accept(new ItemStack(BATTERY_AXE.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
event.accept(new ItemStack(BATTERY_SHOVEL.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
event.accept(new ItemStack(BATTERY_HOE.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
}
|
||||
if (BatteriesConfig.poweredWeaponsEnabled()) {
|
||||
event.accept(new ItemStack(BATTERY_SWORD.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
event.accept(new ItemStack(BATTERY_SHIELD.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
event.accept(new ItemStack(BATTERY_BOW.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
}
|
||||
if (BatteriesConfig.poweredArmorEnabled()) {
|
||||
event.accept(new ItemStack(BATTERY_HELMET.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
event.accept(new ItemStack(BATTERY_CHESTPLATE.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
event.accept(new ItemStack(BATTERY_LEGGINGS.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
event.accept(new ItemStack(BATTERY_BOOTS.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
}
|
||||
event.accept(new ItemStack(BATTERY_BLOCK_ITEM.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
event.accept(new ItemStack(COAL_GENERATOR_ITEM.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
event.accept(new ItemStack(CHARGER_ITEM.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
event.accept(new ItemStack(ENDER_CHARGER_ITEM.get()), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
}
|
||||
|
||||
private static DeferredItem<Item> registerBattery(String name, Tier tier) {
|
||||
return ITEMS.registerItem(name, properties -> new BatteryItem(tier, properties), new Item.Properties().stacksTo(1));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.trunksbomb.batteries;
|
||||
|
||||
import com.trunksbomb.batteries.v21_1.item.PoweredItem;
|
||||
import com.trunksbomb.batteries.v21_1.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 = BatteriesNeoForge121.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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.trunksbomb.batteries;
|
||||
|
||||
import com.trunksbomb.batteries.v21_1.item.PoweredItem;
|
||||
import com.trunksbomb.batteries.v21_1.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 = BatteriesNeoForge121.MODID)
|
||||
public final class PoweredItemNeoForgeEvents {
|
||||
private PoweredItemNeoForgeEvents() {
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package com.trunksbomb.batteries.v21_1.block;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import com.trunksbomb.batteries.BatteriesNeoForge121;
|
||||
import com.trunksbomb.batteries.v21_1.block.entity.BatteryBlockEntity;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryBlockItem;
|
||||
import com.trunksbomb.batteries.v21_1.menu.BatteryBlockMenu;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.SimpleMenuProvider;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.BaseEntityBlock;
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.RenderShape;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.IntegerProperty;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class BatteryBlock extends BaseEntityBlock {
|
||||
public static final MapCodec<BatteryBlock> CODEC = simpleCodec(BatteryBlock::new);
|
||||
public static final net.minecraft.world.level.block.state.properties.EnumProperty<Direction> FACING = HorizontalDirectionalBlock.FACING;
|
||||
public static final IntegerProperty CHARGE = IntegerProperty.create("charge", 0, 4);
|
||||
|
||||
public BatteryBlock(BlockBehaviour.Properties properties) {
|
||||
super(properties);
|
||||
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(CHARGE, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MapCodec<? extends BaseEntityBlock> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<net.minecraft.world.level.block.Block, BlockState> builder) {
|
||||
builder.add(FACING, CHARGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockState rotate(BlockState state, Rotation rotation) {
|
||||
return state.setValue(FACING, rotation.rotate(state.getValue(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockState mirror(BlockState state, Mirror mirror) {
|
||||
return state.rotate(mirror.getRotation(state.getValue(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RenderShape getRenderShape(BlockState state) {
|
||||
return RenderShape.MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, net.minecraft.world.phys.BlockHitResult hitResult) {
|
||||
return openMenu(level, pos, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected net.minecraft.world.ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, net.minecraft.world.phys.BlockHitResult hitResult) {
|
||||
InteractionResult result = openMenu(level, pos, player);
|
||||
return result.consumesAction()
|
||||
? net.minecraft.world.ItemInteractionResult.sidedSuccess(level.isClientSide())
|
||||
: net.minecraft.world.ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
||||
return new BatteryBlockEntity(pos, state);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {
|
||||
return level.isClientSide() ? null : createTickerHelper(type, BatteriesNeoForge121.BATTERY_BLOCK_ENTITY.get(), BatteryBlockEntity::serverTick);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
|
||||
super.setPlacedBy(level, pos, state, placer, stack);
|
||||
if (level.getBlockEntity(pos) instanceof BatteryBlockEntity batteryBlockEntity) {
|
||||
batteryBlockEntity.loadFromItem(stack);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
|
||||
if (!level.isClientSide() && !player.isCreative() && blockEntity instanceof BatteryBlockEntity batteryBlockEntity) {
|
||||
popResource(level, pos, batteryBlockEntity.createDropStack());
|
||||
}
|
||||
super.playerDestroy(level, player, pos, state, blockEntity, tool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
|
||||
super.onPlace(state, level, pos, oldState, movedByPiston);
|
||||
level.invalidateCapabilities(pos);
|
||||
}
|
||||
|
||||
public static BlockBehaviour.Properties batteryBlockProperties() {
|
||||
return BlockBehaviour.Properties.of().strength(2.0F).requiresCorrectToolForDrops();
|
||||
}
|
||||
|
||||
private static InteractionResult openMenu(Level level, BlockPos pos, Player player) {
|
||||
if (!level.isClientSide() && player instanceof ServerPlayer serverPlayer && level.getBlockEntity(pos) instanceof BatteryBlockEntity blockEntity) {
|
||||
MenuProvider provider = new SimpleMenuProvider(
|
||||
(containerId, inventory, menuPlayer) -> BatteryBlockMenu.forBlock(containerId, inventory, blockEntity),
|
||||
Component.translatable("container.batteries.battery_block")
|
||||
);
|
||||
serverPlayer.openMenu(provider, buffer -> BatteryBlockMenu.writeBlockPos(buffer, pos));
|
||||
}
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
package com.trunksbomb.batteries.v21_1.block;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import com.trunksbomb.batteries.BatteriesNeoForge121;
|
||||
import com.trunksbomb.batteries.shared.ChargerBlockData;
|
||||
import com.trunksbomb.batteries.shared.ChargerBlockData.BatteryState;
|
||||
import com.trunksbomb.batteries.v21_1.block.entity.ChargerBlockEntity;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryItem;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.ItemInteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.BaseEntityBlock;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.RenderShape;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
||||
import net.minecraft.world.level.material.MapColor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ChargerBlock extends BaseEntityBlock {
|
||||
public static final EnumProperty<Direction> FACING = HorizontalDirectionalBlock.FACING;
|
||||
public static final EnumProperty<BatteryState> BATTERY = EnumProperty.create("battery", BatteryState.class);
|
||||
public static final MapCodec<ChargerBlock> CODEC = simpleCodec(ChargerBlock::new);
|
||||
|
||||
public ChargerBlock(BlockBehaviour.Properties properties) {
|
||||
super(properties);
|
||||
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(BATTERY, BatteryState.NONE));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MapCodec<? extends BaseEntityBlock> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
builder.add(FACING, BATTERY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockState rotate(BlockState state, Rotation rotation) {
|
||||
return state.setValue(FACING, rotation.rotate(state.getValue(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockState mirror(BlockState state, Mirror mirror) {
|
||||
return this.rotate(state, mirror.getRotation(state.getValue(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RenderShape getRenderShape(BlockState state) {
|
||||
return RenderShape.MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, net.minecraft.world.phys.BlockHitResult hitResult) {
|
||||
return tryRetrieveBattery(state, level, pos, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, net.minecraft.world.phys.BlockHitResult hitResult) {
|
||||
BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||
if (!(blockEntity instanceof ChargerBlockEntity chargerBlockEntity)) {
|
||||
return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
|
||||
}
|
||||
|
||||
if (chargerBlockEntity.hasBattery()) {
|
||||
InteractionResult result = tryRetrieveBattery(state, level, pos, player);
|
||||
return result.consumesAction() ? ItemInteractionResult.sidedSuccess(level.isClientSide()) : ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
|
||||
}
|
||||
|
||||
if (!(stack.getItem() instanceof BatteryItem batteryItem) || !canAcceptBattery(state, batteryItem.tier())) {
|
||||
return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
|
||||
}
|
||||
|
||||
if (!level.isClientSide()) {
|
||||
if (state.is(BatteriesNeoForge121.ENDER_CHARGER.get())) {
|
||||
UUID batteryUuid = BatteryItem.ensureBatteryId(stack);
|
||||
chargerBlockEntity.linkBattery(batteryUuid, player.getUUID());
|
||||
updateBatteryState(level, pos, state, BatteryState.fromTier(batteryItem.tier()));
|
||||
} else {
|
||||
ItemStack remainingStack = chargerBlockEntity.insertBattery(stack);
|
||||
player.setItemInHand(hand, remainingStack);
|
||||
updateBatteryState(level, pos, state, BatteryState.fromTier(batteryItem.tier()));
|
||||
}
|
||||
}
|
||||
|
||||
return ItemInteractionResult.sidedSuccess(level.isClientSide());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
||||
return new ChargerBlockEntity(pos, state);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {
|
||||
return level.isClientSide() ? null : createTickerHelper(type, BatteriesNeoForge121.CHARGER_BLOCK_ENTITY.get(), ChargerBlockEntity::serverTick);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
|
||||
if (blockEntity instanceof ChargerBlockEntity chargerBlockEntity && chargerBlockEntity.hasStoredBattery() && level instanceof ServerLevel serverLevel) {
|
||||
popResource(serverLevel, pos, chargerBlockEntity.extractBattery());
|
||||
}
|
||||
super.playerDestroy(level, player, pos, state, blockEntity, tool);
|
||||
}
|
||||
|
||||
public static BlockBehaviour.Properties chargerProperties() {
|
||||
return BlockBehaviour.Properties.of().mapColor(MapColor.METAL).strength(2.0F).requiresCorrectToolForDrops();
|
||||
}
|
||||
|
||||
private static boolean canAcceptBattery(BlockState state, com.trunksbomb.batteries.item.BatteryItemData.Tier tier) {
|
||||
return ChargerBlockData.canAcceptBattery(state.is(BatteriesNeoForge121.ENDER_CHARGER.get()), tier);
|
||||
}
|
||||
|
||||
private static void updateBatteryState(Level level, BlockPos pos, BlockState state, BatteryState batteryState) {
|
||||
level.setBlock(pos, state.setValue(BATTERY, batteryState), Block.UPDATE_ALL);
|
||||
}
|
||||
|
||||
private static InteractionResult tryRetrieveBattery(BlockState state, Level level, BlockPos pos, Player player) {
|
||||
BlockEntity blockEntity = level.getBlockEntity(pos);
|
||||
if (!(blockEntity instanceof ChargerBlockEntity chargerBlockEntity) || !chargerBlockEntity.hasBattery()) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
if (!level.isClientSide()) {
|
||||
if (state.is(BatteriesNeoForge121.ENDER_CHARGER.get())) {
|
||||
chargerBlockEntity.clearLinkedBattery();
|
||||
updateBatteryState(level, pos, state, BatteryState.NONE);
|
||||
} else {
|
||||
ItemStack extractedBattery = chargerBlockEntity.extractBattery();
|
||||
updateBatteryState(level, pos, state, BatteryState.NONE);
|
||||
if (!player.addItem(extractedBattery)) {
|
||||
player.drop(extractedBattery, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package com.trunksbomb.batteries.v21_1.block;
|
||||
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import com.trunksbomb.batteries.BatteriesNeoForge121;
|
||||
import com.trunksbomb.batteries.v21_1.block.entity.CoalGeneratorBlockEntity;
|
||||
import com.trunksbomb.batteries.v21_1.menu.CoalGeneratorMenu;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.SimpleMenuProvider;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.BaseEntityBlock;
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.RenderShape;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.level.material.MapColor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CoalGeneratorBlock extends BaseEntityBlock {
|
||||
public static final MapCodec<CoalGeneratorBlock> CODEC = simpleCodec(CoalGeneratorBlock::new);
|
||||
public static final net.minecraft.world.level.block.state.properties.EnumProperty<Direction> FACING = HorizontalDirectionalBlock.FACING;
|
||||
public static final BooleanProperty LIT = BlockStateProperties.LIT;
|
||||
|
||||
public CoalGeneratorBlock(BlockBehaviour.Properties properties) {
|
||||
super(properties);
|
||||
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(LIT, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MapCodec<? extends BaseEntityBlock> codec() {
|
||||
return CODEC;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<net.minecraft.world.level.block.Block, BlockState> builder) {
|
||||
builder.add(FACING, LIT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
||||
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockState rotate(BlockState state, Rotation rotation) {
|
||||
return state.setValue(FACING, rotation.rotate(state.getValue(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockState mirror(BlockState state, Mirror mirror) {
|
||||
return this.rotate(state, mirror.getRotation(state.getValue(FACING)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RenderShape getRenderShape(BlockState state) {
|
||||
return RenderShape.MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, net.minecraft.world.phys.BlockHitResult hitResult) {
|
||||
return openMenu(level, pos, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected net.minecraft.world.ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, net.minecraft.world.phys.BlockHitResult hitResult) {
|
||||
InteractionResult result = openMenu(level, pos, player);
|
||||
return result.consumesAction()
|
||||
? net.minecraft.world.ItemInteractionResult.sidedSuccess(level.isClientSide())
|
||||
: net.minecraft.world.ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
||||
return new CoalGeneratorBlockEntity(pos, state);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {
|
||||
return level.isClientSide() ? null : createTickerHelper(type, BatteriesNeoForge121.COAL_GENERATOR_BLOCK_ENTITY.get(), CoalGeneratorBlockEntity::serverTick);
|
||||
}
|
||||
|
||||
public static BlockBehaviour.Properties generatorProperties() {
|
||||
return BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.WOOD)
|
||||
.strength(2.0F)
|
||||
.requiresCorrectToolForDrops();
|
||||
}
|
||||
|
||||
public static void setLit(Level level, BlockPos pos, BlockState state, boolean lit) {
|
||||
if (state.hasProperty(LIT) && state.getValue(LIT) != lit) {
|
||||
level.setBlock(pos, state.setValue(LIT, lit), net.minecraft.world.level.block.Block.UPDATE_CLIENTS);
|
||||
}
|
||||
}
|
||||
|
||||
private static InteractionResult openMenu(Level level, BlockPos pos, Player player) {
|
||||
if (!level.isClientSide() && player instanceof ServerPlayer serverPlayer && level.getBlockEntity(pos) instanceof CoalGeneratorBlockEntity blockEntity) {
|
||||
MenuProvider provider = new SimpleMenuProvider(
|
||||
(containerId, inventory, menuPlayer) -> CoalGeneratorMenu.forBlock(containerId, inventory, blockEntity),
|
||||
Component.translatable("container.batteries.coal_generator")
|
||||
);
|
||||
serverPlayer.openMenu(provider, buffer -> CoalGeneratorMenu.writeBlockPos(buffer, pos));
|
||||
}
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.trunksbomb.batteries.v21_1.block.entity;
|
||||
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
|
||||
final class BatteryBlockEnergyStorage implements IEnergyStorage {
|
||||
private final BatteryBlockEntity blockEntity;
|
||||
|
||||
BatteryBlockEnergyStorage(BatteryBlockEntity blockEntity) {
|
||||
this.blockEntity = blockEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int receiveEnergy(int maxReceive, boolean simulate) {
|
||||
if (maxReceive <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int received = Math.min(maxReceive, Math.min(this.getMaxEnergyStored() - this.getEnergyStored(), this.blockEntity.getMaxTransfer()));
|
||||
if (!simulate && received > 0) {
|
||||
this.blockEntity.setStoredEnergyInternal(this.blockEntity.getStoredEnergy() + received);
|
||||
}
|
||||
return received;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||
if (maxExtract <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int extracted = Math.min(maxExtract, Math.min(this.getEnergyStored(), this.blockEntity.getMaxTransfer()));
|
||||
if (!simulate && extracted > 0) {
|
||||
this.blockEntity.setStoredEnergyInternal(this.blockEntity.getStoredEnergy() - extracted);
|
||||
}
|
||||
return extracted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnergyStored() {
|
||||
return this.blockEntity.getStoredEnergy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxEnergyStored() {
|
||||
return this.blockEntity.getEnergyCapacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtract() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReceive() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
package com.trunksbomb.batteries.v21_1.block.entity;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesNeoForge121;
|
||||
import com.trunksbomb.batteries.item.EnergyTierHelper;
|
||||
import com.trunksbomb.batteries.shared.BatteryBlockData;
|
||||
import com.trunksbomb.batteries.v21_1.block.BatteryBlock;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryBlockItem;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
|
||||
public class BatteryBlockEntity extends BlockEntity {
|
||||
private static final String ENERGY_KEY = "energy";
|
||||
private static final String CAPACITY_KEY = "capacity";
|
||||
|
||||
private int storedEnergy;
|
||||
private int energyCapacity = BatteryBlockItem.BASE_CAPACITY;
|
||||
private BatteryBlockEnergyStorage internalEnergyStorage;
|
||||
private final BatteryBlockData.SideMode[] sideModes = new BatteryBlockData.SideMode[] {
|
||||
BatteryBlockData.SideMode.BOTH, BatteryBlockData.SideMode.BOTH, BatteryBlockData.SideMode.BOTH,
|
||||
BatteryBlockData.SideMode.BOTH, BatteryBlockData.SideMode.BOTH, BatteryBlockData.SideMode.BOTH
|
||||
};
|
||||
|
||||
public BatteryBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(BatteriesNeoForge121.BATTERY_BLOCK_ENTITY.get(), pos, state);
|
||||
}
|
||||
|
||||
public static void serverTick(Level level, BlockPos pos, BlockState state, BatteryBlockEntity blockEntity) {
|
||||
if (blockEntity.storedEnergy <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int remainingTransfer = Math.min(blockEntity.storedEnergy, blockEntity.getMaxTransfer());
|
||||
for (Direction direction : Direction.values()) {
|
||||
if (!blockEntity.canExtract(direction)) {
|
||||
continue;
|
||||
}
|
||||
if (remainingTransfer <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
BlockPos targetPos = pos.relative(direction);
|
||||
if (!level.isLoaded(targetPos)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IEnergyStorage target = level.getCapability(Capabilities.EnergyStorage.BLOCK, targetPos, direction.getOpposite());
|
||||
if (target == null || !target.canReceive()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int accepted = target.receiveEnergy(remainingTransfer, false);
|
||||
if (accepted > 0) {
|
||||
blockEntity.setStoredEnergyInternal(blockEntity.storedEnergy - accepted);
|
||||
remainingTransfer -= accepted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnergyStorage getEnergyStorage(Direction side) {
|
||||
return new BatteryBlockSidedEnergyStorage(this.getInternalEnergyStorage(), side, this);
|
||||
}
|
||||
|
||||
private BatteryBlockEnergyStorage getInternalEnergyStorage() {
|
||||
if (this.internalEnergyStorage == null) {
|
||||
this.internalEnergyStorage = new BatteryBlockEnergyStorage(this);
|
||||
}
|
||||
return this.internalEnergyStorage;
|
||||
}
|
||||
|
||||
public int getStoredEnergy() {
|
||||
return this.storedEnergy;
|
||||
}
|
||||
|
||||
public int getEnergyCapacity() {
|
||||
return this.energyCapacity;
|
||||
}
|
||||
|
||||
public int getMaxTransfer() {
|
||||
return EnergyTierHelper.transferRateForCapacity(this.energyCapacity);
|
||||
}
|
||||
|
||||
public BatteryBlockData.SideMode getSideMode(Direction direction) {
|
||||
return this.sideModes[direction.ordinal()];
|
||||
}
|
||||
|
||||
public void setSideMode(Direction direction, BatteryBlockData.SideMode mode) {
|
||||
this.sideModes[direction.ordinal()] = mode;
|
||||
this.setChanged();
|
||||
if (this.level != null) {
|
||||
this.level.invalidateCapabilities(this.worldPosition);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canInsert(Direction direction) {
|
||||
BatteryBlockData.SideMode mode = this.getSideMode(direction);
|
||||
return mode == BatteryBlockData.SideMode.INPUT || mode == BatteryBlockData.SideMode.BOTH;
|
||||
}
|
||||
|
||||
public boolean canExtract(Direction direction) {
|
||||
BatteryBlockData.SideMode mode = this.getSideMode(direction);
|
||||
return mode == BatteryBlockData.SideMode.OUTPUT || mode == BatteryBlockData.SideMode.BOTH;
|
||||
}
|
||||
|
||||
public static Direction directionForIndex(int index) {
|
||||
return BatteryBlockData.directionForIndex(index);
|
||||
}
|
||||
|
||||
public void loadFromItem(ItemStack stack) {
|
||||
BatteryBlockItem.initializeDefaults(stack);
|
||||
this.energyCapacity = BatteryBlockItem.getEnergyCapacity(stack);
|
||||
this.storedEnergy = Math.min(BatteryBlockItem.getStoredEnergy(stack), this.energyCapacity);
|
||||
this.internalEnergyStorage = null;
|
||||
this.refreshState();
|
||||
}
|
||||
|
||||
public ItemStack createDropStack() {
|
||||
ItemStack stack = new ItemStack(BatteriesNeoForge121.BATTERY_BLOCK_ITEM.get());
|
||||
BatteryBlockItem.setEnergyCapacity(stack, this.energyCapacity);
|
||||
BatteryBlockItem.setStoredEnergy(stack, this.storedEnergy);
|
||||
return stack;
|
||||
}
|
||||
|
||||
void setStoredEnergyInternal(int energy) {
|
||||
this.storedEnergy = Math.max(0, Math.min(energy, this.energyCapacity));
|
||||
this.refreshState();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
super.loadAdditional(tag, registries);
|
||||
this.energyCapacity = Math.max(BatteryBlockItem.BASE_CAPACITY, tag.contains(CAPACITY_KEY) ? tag.getInt(CAPACITY_KEY) : BatteryBlockItem.BASE_CAPACITY);
|
||||
this.storedEnergy = Math.max(0, Math.min(tag.contains(ENERGY_KEY) ? tag.getInt(ENERGY_KEY) : 0, this.energyCapacity));
|
||||
for (Direction direction : Direction.values()) {
|
||||
int ordinal = tag.contains("side_" + direction.getSerializedName()) ? tag.getInt("side_" + direction.getSerializedName()) : BatteryBlockData.SideMode.BOTH.ordinal();
|
||||
this.sideModes[direction.ordinal()] = BatteryBlockData.SideMode.values()[Math.max(0, Math.min(BatteryBlockData.SideMode.values().length - 1, ordinal))];
|
||||
}
|
||||
this.internalEnergyStorage = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
super.saveAdditional(tag, registries);
|
||||
tag.putInt(CAPACITY_KEY, this.energyCapacity);
|
||||
tag.putInt(ENERGY_KEY, this.storedEnergy);
|
||||
for (Direction direction : Direction.values()) {
|
||||
tag.putInt("side_" + direction.getSerializedName(), this.sideModes[direction.ordinal()].ordinal());
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshState() {
|
||||
this.setChanged();
|
||||
if (this.level == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BlockState state = this.getBlockState();
|
||||
int targetCharge = BatteryBlockData.chargeStage(this.storedEnergy, this.energyCapacity);
|
||||
if (state.hasProperty(BatteryBlock.CHARGE) && state.getValue(BatteryBlock.CHARGE) != targetCharge) {
|
||||
this.level.setBlock(this.worldPosition, state.setValue(BatteryBlock.CHARGE, targetCharge), net.minecraft.world.level.block.Block.UPDATE_CLIENTS);
|
||||
}
|
||||
this.level.invalidateCapabilities(this.worldPosition);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.trunksbomb.batteries.v21_1.block.entity;
|
||||
|
||||
import net.minecraft.core.Direction;
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
|
||||
final class BatteryBlockSidedEnergyStorage implements IEnergyStorage {
|
||||
private final IEnergyStorage delegate;
|
||||
private final Direction side;
|
||||
private final BatteryBlockEntity blockEntity;
|
||||
|
||||
BatteryBlockSidedEnergyStorage(IEnergyStorage delegate, Direction side, BatteryBlockEntity blockEntity) {
|
||||
this.delegate = delegate;
|
||||
this.side = side;
|
||||
this.blockEntity = blockEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int receiveEnergy(int maxReceive, boolean simulate) {
|
||||
if (maxReceive <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (this.side != null && !this.blockEntity.canInsert(this.side)) {
|
||||
return 0;
|
||||
}
|
||||
return this.delegate.receiveEnergy(maxReceive, simulate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||
if (maxExtract <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (this.side != null && !this.blockEntity.canExtract(this.side)) {
|
||||
return 0;
|
||||
}
|
||||
return this.delegate.extractEnergy(maxExtract, simulate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnergyStored() {
|
||||
return this.delegate.getEnergyStored();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxEnergyStored() {
|
||||
return this.delegate.getMaxEnergyStored();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtract() {
|
||||
return this.side == null || this.blockEntity.canExtract(this.side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReceive() {
|
||||
return this.side == null || this.blockEntity.canInsert(this.side);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package com.trunksbomb.batteries.v21_1.block.entity;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesConfig;
|
||||
import com.trunksbomb.batteries.BatteriesNeoForge121;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryItem;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
|
||||
public class ChargerBlockEntity extends BlockEntity {
|
||||
public static final UUID DEFAULT_UUID = new UUID(0L, 0L);
|
||||
private ItemStack battery = ItemStack.EMPTY;
|
||||
private UUID linkedBatteryUuid = DEFAULT_UUID;
|
||||
private UUID linkedPlayerUuid = DEFAULT_UUID;
|
||||
private ChargerEnergyStorage energyStorage;
|
||||
|
||||
public ChargerBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(BatteriesNeoForge121.CHARGER_BLOCK_ENTITY.get(), pos, state);
|
||||
}
|
||||
|
||||
public static void serverTick(Level level, BlockPos pos, BlockState state, ChargerBlockEntity blockEntity) {
|
||||
if (!BatteriesConfig.chargerGeneratesCreativePower()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack battery = blockEntity.getChargeTarget();
|
||||
if (battery.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
IEnergyStorage batteryStorage = BatteryItem.createEnergyHandler(battery);
|
||||
if (batteryStorage == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int inserted = batteryStorage.receiveEnergy(com.trunksbomb.batteries.item.BatteryItemData.getMaxTransfer(((BatteryItem) battery.getItem()).tier()), false);
|
||||
if (inserted > 0) {
|
||||
blockEntity.onBatteryChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasBattery() {
|
||||
return this.hasStoredBattery() || this.hasLinkedBattery();
|
||||
}
|
||||
|
||||
public boolean hasStoredBattery() {
|
||||
return !this.battery.isEmpty();
|
||||
}
|
||||
|
||||
public boolean hasLinkedBattery() {
|
||||
return !DEFAULT_UUID.equals(this.linkedBatteryUuid) && !DEFAULT_UUID.equals(this.linkedPlayerUuid);
|
||||
}
|
||||
|
||||
public ItemStack insertBattery(ItemStack stack) {
|
||||
if (this.hasBattery() || !(stack.getItem() instanceof BatteryItem)) {
|
||||
return stack;
|
||||
}
|
||||
|
||||
this.battery = stack.copyWithCount(1);
|
||||
stack.shrink(1);
|
||||
this.onBatteryChanged();
|
||||
return stack;
|
||||
}
|
||||
|
||||
public ItemStack extractBattery() {
|
||||
if (this.battery.isEmpty()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
ItemStack extracted = this.battery;
|
||||
this.battery = ItemStack.EMPTY;
|
||||
this.onBatteryChanged();
|
||||
return extracted;
|
||||
}
|
||||
|
||||
public void linkBattery(UUID batteryUuid, UUID playerUuid) {
|
||||
this.linkedBatteryUuid = batteryUuid;
|
||||
this.linkedPlayerUuid = playerUuid;
|
||||
this.onBatteryChanged();
|
||||
}
|
||||
|
||||
public void clearLinkedBattery() {
|
||||
this.linkedBatteryUuid = DEFAULT_UUID;
|
||||
this.linkedPlayerUuid = DEFAULT_UUID;
|
||||
this.onBatteryChanged();
|
||||
}
|
||||
|
||||
public IEnergyStorage getEnergyStorage(Direction side) {
|
||||
if (this.energyStorage == null) {
|
||||
this.energyStorage = new ChargerEnergyStorage(this);
|
||||
}
|
||||
return this.energyStorage;
|
||||
}
|
||||
|
||||
ItemStack getChargeTarget() {
|
||||
if (this.hasStoredBattery()) {
|
||||
return this.battery;
|
||||
}
|
||||
|
||||
if (this.level instanceof net.minecraft.server.level.ServerLevel serverLevel && this.hasLinkedBattery()) {
|
||||
ServerPlayer player = serverLevel.getServer().getPlayerList().getPlayer(this.linkedPlayerUuid);
|
||||
if (player != null) {
|
||||
return BatteryItem.findLinkedEnderBattery(player, this.linkedBatteryUuid);
|
||||
}
|
||||
}
|
||||
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
super.loadAdditional(tag, registries);
|
||||
this.battery = tag.contains("battery") ? ItemStack.parseOptional(registries, tag.getCompound("battery")) : ItemStack.EMPTY;
|
||||
this.linkedBatteryUuid = parseUuid(tag.getString("linked_battery_uuid"));
|
||||
this.linkedPlayerUuid = parseUuid(tag.getString("linked_player_uuid"));
|
||||
this.energyStorage = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
super.saveAdditional(tag, registries);
|
||||
if (!this.battery.isEmpty()) {
|
||||
tag.put("battery", this.battery.saveOptional(registries));
|
||||
}
|
||||
if (this.hasLinkedBattery()) {
|
||||
tag.putString("linked_battery_uuid", this.linkedBatteryUuid.toString());
|
||||
tag.putString("linked_player_uuid", this.linkedPlayerUuid.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void onBatteryChanged() {
|
||||
this.setChanged();
|
||||
if (this.level != null) {
|
||||
this.level.invalidateCapabilities(this.worldPosition);
|
||||
}
|
||||
}
|
||||
|
||||
private static UUID parseUuid(String value) {
|
||||
return value == null || value.isBlank() ? DEFAULT_UUID : UUID.fromString(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.trunksbomb.batteries.v21_1.block.entity;
|
||||
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
|
||||
final class ChargerEnergyStorage implements IEnergyStorage {
|
||||
private final ChargerBlockEntity blockEntity;
|
||||
|
||||
ChargerEnergyStorage(ChargerBlockEntity blockEntity) {
|
||||
this.blockEntity = blockEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int receiveEnergy(int maxReceive, boolean simulate) {
|
||||
ItemStack battery = this.blockEntity.getChargeTarget();
|
||||
if (battery.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
IEnergyStorage storage = BatteryItem.createEnergyHandler(battery);
|
||||
if (storage == null || !storage.canReceive()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int received = storage.receiveEnergy(maxReceive, simulate);
|
||||
if (!simulate && received > 0) {
|
||||
this.blockEntity.setChanged();
|
||||
}
|
||||
return received;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnergyStored() {
|
||||
ItemStack battery = this.blockEntity.getChargeTarget();
|
||||
return battery.isEmpty() ? 0 : BatteryItem.getStoredEnergy(battery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxEnergyStored() {
|
||||
ItemStack battery = this.blockEntity.getChargeTarget();
|
||||
return battery.isEmpty() ? 0 : BatteryItem.getEnergyCapacity(battery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtract() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReceive() {
|
||||
ItemStack battery = this.blockEntity.getChargeTarget();
|
||||
return !battery.isEmpty() && BatteryItem.getStoredEnergy(battery) < BatteryItem.getEnergyCapacity(battery);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
package com.trunksbomb.batteries.v21_1.block.entity;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesConfig;
|
||||
import com.trunksbomb.batteries.BatteriesNeoForge121;
|
||||
import com.trunksbomb.batteries.item.EnergyTierHelper;
|
||||
import com.trunksbomb.batteries.v21_1.block.CoalGeneratorBlock;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryBlockItem;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.WorldlyContainer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
import net.neoforged.neoforge.items.IItemHandler;
|
||||
|
||||
public class CoalGeneratorBlockEntity extends BlockEntity implements WorldlyContainer {
|
||||
private static final int[] ACCESSIBLE_SLOTS = new int[] {0};
|
||||
private static final String ENERGY_KEY = "energy";
|
||||
private static final String BURN_TIME_KEY = "burn_time";
|
||||
private static final String MAX_BURN_TIME_KEY = "max_burn_time";
|
||||
|
||||
private final SimpleContainer fuelSlot = new SimpleContainer(1) {
|
||||
@Override
|
||||
public void setChanged() {
|
||||
super.setChanged();
|
||||
CoalGeneratorBlockEntity.this.setChanged();
|
||||
}
|
||||
};
|
||||
|
||||
private int storedEnergy;
|
||||
private int burnTimeRemaining;
|
||||
private int maxBurnTime;
|
||||
private CoalGeneratorEnergyStorage internalEnergyStorage;
|
||||
private GeneratorOutputEnergyStorage outputEnergyStorage;
|
||||
private CoalGeneratorItemHandler itemHandler;
|
||||
|
||||
public CoalGeneratorBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(BatteriesNeoForge121.COAL_GENERATOR_BLOCK_ENTITY.get(), pos, state);
|
||||
}
|
||||
|
||||
public static void serverTick(Level level, BlockPos pos, BlockState state, CoalGeneratorBlockEntity blockEntity) {
|
||||
boolean wasBurning = blockEntity.isBurning();
|
||||
blockEntity.tickGeneration(level);
|
||||
if (wasBurning != blockEntity.isBurning()) {
|
||||
CoalGeneratorBlock.setLit(level, pos, state, blockEntity.isBurning());
|
||||
}
|
||||
blockEntity.tickOutput(level, pos);
|
||||
}
|
||||
|
||||
public SimpleContainer fuelSlot() {
|
||||
return this.fuelSlot;
|
||||
}
|
||||
|
||||
public IEnergyStorage getEnergyStorage(Direction side) {
|
||||
if (this.outputEnergyStorage == null) {
|
||||
this.outputEnergyStorage = new GeneratorOutputEnergyStorage(this.getInternalEnergyStorage());
|
||||
}
|
||||
return this.outputEnergyStorage;
|
||||
}
|
||||
|
||||
public IItemHandler getItemHandler(Direction side) {
|
||||
if (this.itemHandler == null) {
|
||||
this.itemHandler = new CoalGeneratorItemHandler(this);
|
||||
}
|
||||
return this.itemHandler;
|
||||
}
|
||||
|
||||
public int getStoredEnergy() {
|
||||
return this.storedEnergy;
|
||||
}
|
||||
|
||||
public int getEnergyCapacity() {
|
||||
return BatteryBlockItem.BASE_CAPACITY;
|
||||
}
|
||||
|
||||
public int getBurnTimeRemaining() {
|
||||
return this.burnTimeRemaining;
|
||||
}
|
||||
|
||||
public int getMaxBurnTime() {
|
||||
return this.maxBurnTime;
|
||||
}
|
||||
|
||||
public boolean isBurning() {
|
||||
return this.burnTimeRemaining > 0;
|
||||
}
|
||||
|
||||
public int getMaxTransfer() {
|
||||
return EnergyTierHelper.transferRateForCapacity(this.getEnergyCapacity());
|
||||
}
|
||||
|
||||
private CoalGeneratorEnergyStorage getInternalEnergyStorage() {
|
||||
if (this.internalEnergyStorage == null) {
|
||||
this.internalEnergyStorage = new CoalGeneratorEnergyStorage(this);
|
||||
}
|
||||
return this.internalEnergyStorage;
|
||||
}
|
||||
|
||||
private void tickGeneration(Level level) {
|
||||
if (this.burnTimeRemaining <= 0 && this.storedEnergy < this.getEnergyCapacity()) {
|
||||
ItemStack fuel = this.fuelSlot.getItem(0);
|
||||
int burnTime = getFuelBurnTime(level, fuel);
|
||||
if (burnTime > 0) {
|
||||
this.burnTimeRemaining = burnTime;
|
||||
this.maxBurnTime = burnTime;
|
||||
fuel.shrink(1);
|
||||
if (fuel.isEmpty()) {
|
||||
this.fuelSlot.setItem(0, ItemStack.EMPTY);
|
||||
}
|
||||
this.setChanged();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.burnTimeRemaining > 0 && this.storedEnergy < this.getEnergyCapacity()) {
|
||||
this.getInternalEnergyStorage().set(Math.min(this.getEnergyCapacity(), this.storedEnergy + BatteriesConfig.generatorEnergyPerTick()));
|
||||
this.burnTimeRemaining--;
|
||||
this.setChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void tickOutput(Level level, BlockPos pos) {
|
||||
if (this.storedEnergy <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int remainingTransfer = Math.min(this.storedEnergy, this.getMaxTransfer());
|
||||
IEnergyStorage source = this.getInternalEnergyStorage();
|
||||
|
||||
for (Direction direction : Direction.values()) {
|
||||
if (remainingTransfer <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
BlockPos targetPos = pos.relative(direction);
|
||||
if (!level.isLoaded(targetPos)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IEnergyStorage target = level.getCapability(Capabilities.EnergyStorage.BLOCK, targetPos, direction.getOpposite());
|
||||
if (target == null || !target.canReceive()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int accepted = target.receiveEnergy(remainingTransfer, false);
|
||||
if (accepted <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int extracted = source.extractEnergy(accepted, false);
|
||||
if (extracted > 0) {
|
||||
remainingTransfer -= extracted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
super.loadAdditional(tag, registries);
|
||||
this.storedEnergy = Math.max(0, Math.min(tag.contains(ENERGY_KEY) ? tag.getInt(ENERGY_KEY) : 0, this.getEnergyCapacity()));
|
||||
this.burnTimeRemaining = Math.max(0, tag.contains(BURN_TIME_KEY) ? tag.getInt(BURN_TIME_KEY) : 0);
|
||||
this.maxBurnTime = Math.max(0, tag.contains(MAX_BURN_TIME_KEY) ? tag.getInt(MAX_BURN_TIME_KEY) : 0);
|
||||
if (tag.contains("fuel")) {
|
||||
this.fuelSlot.setItem(0, ItemStack.parseOptional(registries, tag.getCompound("fuel")));
|
||||
} else {
|
||||
this.fuelSlot.setItem(0, ItemStack.EMPTY);
|
||||
}
|
||||
this.internalEnergyStorage = null;
|
||||
this.outputEnergyStorage = null;
|
||||
this.itemHandler = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
super.saveAdditional(tag, registries);
|
||||
tag.putInt(ENERGY_KEY, this.storedEnergy);
|
||||
tag.putInt(BURN_TIME_KEY, this.burnTimeRemaining);
|
||||
tag.putInt(MAX_BURN_TIME_KEY, this.maxBurnTime);
|
||||
if (!this.fuelSlot.getItem(0).isEmpty()) {
|
||||
tag.put("fuel", this.fuelSlot.getItem(0).saveOptional(registries));
|
||||
}
|
||||
}
|
||||
|
||||
void setStoredEnergyInternal(int energy) {
|
||||
this.storedEnergy = Math.max(0, Math.min(energy, this.getEnergyCapacity()));
|
||||
this.setChanged();
|
||||
if (this.level != null) {
|
||||
this.level.invalidateCapabilities(this.worldPosition);
|
||||
}
|
||||
}
|
||||
|
||||
private static int getFuelBurnTime(Level level, ItemStack stack) {
|
||||
if (!isFuel(level, stack)) {
|
||||
return 0;
|
||||
}
|
||||
return AbstractFurnaceBlockEntity.getFuel().getOrDefault(stack.getItem(), 0);
|
||||
}
|
||||
|
||||
public static boolean isFuel(Level level, ItemStack stack) {
|
||||
return !stack.isEmpty() && AbstractFurnaceBlockEntity.isFuel(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getSlotsForFace(Direction side) {
|
||||
return ACCESSIBLE_SLOTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlaceItemThroughFace(int index, ItemStack stack, Direction direction) {
|
||||
return index == 0 && this.level != null && isFuel(this.level, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTakeItemThroughFace(int index, ItemStack stack, Direction direction) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContainerSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return this.fuelSlot.getItem(0).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItem(int slot) {
|
||||
return slot == 0 ? this.fuelSlot.getItem(0) : ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack removeItem(int slot, int amount) {
|
||||
if (slot != 0) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
ItemStack removed = this.fuelSlot.removeItem(slot, amount);
|
||||
if (!removed.isEmpty()) {
|
||||
this.setChanged();
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack removeItemNoUpdate(int slot) {
|
||||
return slot == 0 ? this.fuelSlot.removeItemNoUpdate(0) : ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(int slot, ItemStack stack) {
|
||||
if (slot == 0) {
|
||||
this.fuelSlot.setItem(0, stack);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(Player player) {
|
||||
return this.level != null
|
||||
&& this.level.getBlockEntity(this.worldPosition) == this
|
||||
&& player.distanceToSqr(this.worldPosition.getX() + 0.5D, this.worldPosition.getY() + 0.5D, this.worldPosition.getZ() + 0.5D) <= 64.0D;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlaceItem(int slot, ItemStack stack) {
|
||||
return slot == 0 && this.level != null && isFuel(this.level, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearContent() {
|
||||
this.fuelSlot.setItem(0, ItemStack.EMPTY);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.trunksbomb.batteries.v21_1.block.entity;
|
||||
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
|
||||
final class CoalGeneratorEnergyStorage implements IEnergyStorage {
|
||||
private final CoalGeneratorBlockEntity blockEntity;
|
||||
|
||||
CoalGeneratorEnergyStorage(CoalGeneratorBlockEntity blockEntity) {
|
||||
this.blockEntity = blockEntity;
|
||||
}
|
||||
|
||||
void set(int energy) {
|
||||
this.blockEntity.setStoredEnergyInternal(energy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int receiveEnergy(int maxReceive, boolean simulate) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||
if (maxExtract <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int extracted = Math.min(maxExtract, Math.min(this.getEnergyStored(), this.blockEntity.getMaxTransfer()));
|
||||
if (!simulate && extracted > 0) {
|
||||
this.blockEntity.setStoredEnergyInternal(this.blockEntity.getStoredEnergy() - extracted);
|
||||
}
|
||||
return extracted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnergyStored() {
|
||||
return this.blockEntity.getStoredEnergy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxEnergyStored() {
|
||||
return this.blockEntity.getEnergyCapacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtract() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReceive() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.trunksbomb.batteries.v21_1.block.entity;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.neoforged.neoforge.items.IItemHandler;
|
||||
|
||||
public class CoalGeneratorItemHandler implements IItemHandler {
|
||||
private final CoalGeneratorBlockEntity blockEntity;
|
||||
|
||||
public CoalGeneratorItemHandler(CoalGeneratorBlockEntity blockEntity) {
|
||||
this.blockEntity = blockEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlots() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getStackInSlot(int slot) {
|
||||
validateSlot(slot);
|
||||
return this.blockEntity.fuelSlot().getItem(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
|
||||
validateSlot(slot);
|
||||
if (stack.isEmpty() || this.blockEntity.getLevel() == null || !CoalGeneratorBlockEntity.isFuel(this.blockEntity.getLevel(), stack)) {
|
||||
return stack;
|
||||
}
|
||||
|
||||
ItemStack current = this.blockEntity.fuelSlot().getItem(0);
|
||||
if (!current.isEmpty() && !ItemStack.isSameItemSameComponents(current, stack)) {
|
||||
return stack;
|
||||
}
|
||||
|
||||
int inserted = Math.min(stack.getCount(), this.getSlotLimit(slot) - current.getCount());
|
||||
if (inserted <= 0) {
|
||||
return stack;
|
||||
}
|
||||
|
||||
if (!simulate) {
|
||||
if (current.isEmpty()) {
|
||||
this.blockEntity.fuelSlot().setItem(0, stack.copyWithCount(inserted));
|
||||
} else {
|
||||
current.grow(inserted);
|
||||
this.blockEntity.fuelSlot().setItem(0, current);
|
||||
}
|
||||
this.blockEntity.setChanged();
|
||||
if (this.blockEntity.getLevel() != null) {
|
||||
this.blockEntity.getLevel().invalidateCapabilities(this.blockEntity.getBlockPos());
|
||||
}
|
||||
}
|
||||
|
||||
if (inserted == stack.getCount()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
ItemStack remainder = stack.copy();
|
||||
remainder.shrink(inserted);
|
||||
return remainder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack extractItem(int slot, int amount, boolean simulate) {
|
||||
validateSlot(slot);
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSlotLimit(int slot) {
|
||||
validateSlot(slot);
|
||||
ItemStack current = this.blockEntity.fuelSlot().getItem(0);
|
||||
return current.isEmpty() ? 64 : current.getMaxStackSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemValid(int slot, ItemStack stack) {
|
||||
validateSlot(slot);
|
||||
return this.blockEntity.getLevel() != null && CoalGeneratorBlockEntity.isFuel(this.blockEntity.getLevel(), stack);
|
||||
}
|
||||
|
||||
private static void validateSlot(int slot) {
|
||||
if (slot != 0) {
|
||||
throw new IndexOutOfBoundsException("Coal generator only has one slot");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.trunksbomb.batteries.v21_1.block.entity;
|
||||
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
|
||||
final class GeneratorOutputEnergyStorage implements IEnergyStorage {
|
||||
private final IEnergyStorage delegate;
|
||||
|
||||
GeneratorOutputEnergyStorage(IEnergyStorage delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int receiveEnergy(int maxReceive, boolean simulate) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||
return this.delegate.extractEnergy(maxExtract, simulate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnergyStored() {
|
||||
return this.delegate.getEnergyStored();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxEnergyStored() {
|
||||
return this.delegate.getMaxEnergyStored();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtract() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReceive() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
package com.trunksbomb.batteries.v21_1.client.screen;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesNeoForge121;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryItem;
|
||||
import com.trunksbomb.batteries.v21_1.menu.BatteriesMenu;
|
||||
import java.util.List;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class BatteriesScreen extends AbstractContainerScreen<BatteriesMenu> {
|
||||
private static final ResourceLocation TEXTURE = ResourceLocation.fromNamespaceAndPath(BatteriesNeoForge121.MODID, "textures/battery_gui.png");
|
||||
|
||||
private static final int WIDTH = 200;
|
||||
private static final int HEIGHT = 164;
|
||||
private static final int BUTTON_WIDTH = 20;
|
||||
private static final int BUTTON_HEIGHT = 18;
|
||||
private static final int BUTTON_SCREEN_GAP_X = 7;
|
||||
private static final int BUTTON_SCREEN_GAP_Y = 3;
|
||||
private static final int BUTTON_START_X = 48;
|
||||
private static final int BUTTON_START_Y = 39;
|
||||
private static final int INVENTORY_START_X = 32;
|
||||
private static final int INVENTORY_START_Y = 19;
|
||||
private static final int ARMOR_START_X = 7;
|
||||
private static final int ARMOR_START_Y = 19;
|
||||
private static final int BUTTON_TEXTURE_GAP = 1;
|
||||
private static final int BUTTON_TEXTURE_START_X = 201;
|
||||
private static final int BUTTON_TEXTURE_START_Y = 0;
|
||||
private static final int ARMOR_TEXTURE_X = 42;
|
||||
private static final int ARMOR_TEXTURE_Y = 170;
|
||||
private static final int CHECK_TEXTURE_X = 25;
|
||||
private static final int CHECK_TEXTURE_Y = 170;
|
||||
private static final int PLUS_TEXTURE_X = 144;
|
||||
private static final int PLUS_TEXTURE_Y = 170;
|
||||
|
||||
public BatteriesScreen(BatteriesMenu menu, Inventory playerInventory, Component title) {
|
||||
super(menu, playerInventory, title);
|
||||
this.imageWidth = WIDTH;
|
||||
this.imageHeight = HEIGHT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY) {
|
||||
guiGraphics.blit(TEXTURE, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight, 256, 256);
|
||||
drawButtons(guiGraphics, mouseX, mouseY);
|
||||
drawOverlays(guiGraphics);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderLabels(GuiGraphics guiGraphics, int mouseX, int mouseY) {
|
||||
renderTitle(guiGraphics);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
|
||||
this.renderBackground(guiGraphics, mouseX, mouseY, partialTick);
|
||||
super.render(guiGraphics, mouseX, mouseY, partialTick);
|
||||
this.renderTooltip(guiGraphics, mouseX, mouseY);
|
||||
renderCustomTooltip(guiGraphics, mouseX, mouseY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
for (int index = 0; index < this.menu.buttonCount(); index++) {
|
||||
if (isBatteryModeToggle(index)) {
|
||||
if (buttonBounds(0, 1).contains(mouseX, mouseY)) {
|
||||
pressMenuButton(0);
|
||||
return true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
Bounds bounds = buttonBounds(indexToRow(index), indexToColumn(index));
|
||||
if (bounds.contains(mouseX, mouseY)) {
|
||||
pressMenuButton(index);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return super.mouseClicked(mouseX, mouseY, button);
|
||||
}
|
||||
|
||||
private void drawButtons(GuiGraphics guiGraphics, int mouseX, int mouseY) {
|
||||
drawBatteryModeButton(guiGraphics, mouseX, mouseY);
|
||||
|
||||
for (int index = 2; index < this.menu.buttonCount(); index++) {
|
||||
Bounds bounds = buttonBounds(indexToRow(index), indexToColumn(index));
|
||||
drawButton(guiGraphics, bounds, index, bounds.contains(mouseX, mouseY));
|
||||
}
|
||||
}
|
||||
|
||||
private void drawBatteryModeButton(GuiGraphics guiGraphics, int mouseX, int mouseY) {
|
||||
Bounds bounds = buttonBounds(0, 1);
|
||||
boolean hovering = bounds.contains(mouseX, mouseY);
|
||||
int textureIndex = this.menu.isButtonEnabled(0) ? 0 : 1;
|
||||
int offset = hovering ? BUTTON_WIDTH + BUTTON_TEXTURE_GAP : 0;
|
||||
guiGraphics.blit(TEXTURE, bounds.x, bounds.y,
|
||||
BUTTON_TEXTURE_START_X + offset,
|
||||
BUTTON_TEXTURE_START_Y + textureIndex * (BUTTON_HEIGHT + BUTTON_TEXTURE_GAP),
|
||||
BUTTON_WIDTH, BUTTON_HEIGHT, 256, 256);
|
||||
}
|
||||
|
||||
private void drawButton(GuiGraphics guiGraphics, Bounds bounds, int index, boolean hovering) {
|
||||
int offset = hovering ? BUTTON_WIDTH + BUTTON_TEXTURE_GAP : 0;
|
||||
guiGraphics.blit(TEXTURE, bounds.x, bounds.y,
|
||||
BUTTON_TEXTURE_START_X + offset,
|
||||
BUTTON_TEXTURE_START_Y + index * (BUTTON_HEIGHT + BUTTON_TEXTURE_GAP),
|
||||
BUTTON_WIDTH, BUTTON_HEIGHT, 256, 256);
|
||||
}
|
||||
|
||||
private void drawOverlays(GuiGraphics guiGraphics) {
|
||||
for (int index = 2; index < this.menu.buttonCount(); index++) {
|
||||
if (!this.menu.isButtonEnabled(index)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Bounds bounds = buttonBounds(indexToRow(index), indexToColumn(index));
|
||||
guiGraphics.blit(TEXTURE, bounds.x + 4, bounds.y + 4, CHECK_TEXTURE_X, CHECK_TEXTURE_Y, 16, 16, 256, 256);
|
||||
}
|
||||
|
||||
for (int slot = 0; slot < BatteriesMenu.FILTER_SLOT_COUNT; slot++) {
|
||||
if (this.menu.isFilterSlotEmpty(slot)) {
|
||||
guiGraphics.blit(TEXTURE, this.leftPos + INVENTORY_START_X + 18 * slot, this.topPos + INVENTORY_START_Y,
|
||||
PLUS_TEXTURE_X, PLUS_TEXTURE_Y, 16, 16, 256, 256);
|
||||
}
|
||||
}
|
||||
|
||||
for (int armorIndex = 0; armorIndex < 4; armorIndex++) {
|
||||
int slot = 39 - armorIndex;
|
||||
ItemStack stack = this.menu.playerInventoryItem(slot);
|
||||
if (stack.isEmpty()) {
|
||||
guiGraphics.blit(TEXTURE, this.leftPos + ARMOR_START_X, this.topPos + ARMOR_START_Y + armorIndex * 18,
|
||||
ARMOR_TEXTURE_X + armorIndex * 17, ARMOR_TEXTURE_Y, 16, 16, 256, 256);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.menu.playerInventoryItem(40).isEmpty()) {
|
||||
guiGraphics.blit(TEXTURE, this.leftPos + ARMOR_START_X, this.topPos + 91, 110, 170, 16, 16, 256, 256);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderCustomTooltip(GuiGraphics guiGraphics, int mouseX, int mouseY) {
|
||||
String hoverKey = hoveredButtonTranslationKey(mouseX, mouseY);
|
||||
if (hoverKey != null) {
|
||||
guiGraphics.renderTooltip(this.font, Component.translatable(hoverKey), mouseX, mouseY);
|
||||
}
|
||||
}
|
||||
|
||||
private String hoveredButtonTranslationKey(int mouseX, int mouseY) {
|
||||
if (buttonBounds(0, 1).contains(mouseX, mouseY)) {
|
||||
return this.menu.isButtonEnabled(0)
|
||||
? "batteries.gui.button.whitelist"
|
||||
: "batteries.gui.button.blacklist";
|
||||
}
|
||||
|
||||
for (int index = 2; index < this.menu.buttonCount(); index++) {
|
||||
Bounds bounds = buttonBounds(indexToRow(index), indexToColumn(index));
|
||||
if (bounds.contains(mouseX, mouseY)) {
|
||||
return BatteriesMenu.buttonTranslationKey(index);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void pressMenuButton(int index) {
|
||||
if (this.minecraft.gameMode == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.minecraft.gameMode.handleInventoryButtonClick(this.menu.containerId, index);
|
||||
this.menu.toggleClientPreview(index);
|
||||
}
|
||||
|
||||
private Component titleText() {
|
||||
ItemStack battery = this.menu.batteryStack();
|
||||
if (!(battery.getItem() instanceof BatteryItem)) {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
return Component.literal(battery.getHoverName().getString()
|
||||
+ " - "
|
||||
+ BatteryItem.formatCompactAmount(BatteryItem.getStoredEnergy(battery))
|
||||
+ " / "
|
||||
+ BatteryItem.formatCompactAmount(BatteryItem.getEnergyCapacity(battery))
|
||||
+ " E");
|
||||
}
|
||||
|
||||
private void renderTitle(GuiGraphics guiGraphics) {
|
||||
Component title = titleText();
|
||||
int leftAlignedX = INVENTORY_START_X;
|
||||
int titleY = 8;
|
||||
int maxWidth = this.imageWidth - INVENTORY_START_X - 8;
|
||||
int textWidth = this.font.width(title);
|
||||
float scale = textWidth > maxWidth ? maxWidth / (float) textWidth : 1.0F;
|
||||
|
||||
guiGraphics.pose().pushPose();
|
||||
guiGraphics.pose().scale(scale, scale, 1.0F);
|
||||
guiGraphics.drawString(this.font, title, Math.round(leftAlignedX / scale), Math.round(titleY / scale), 0xFF202020, false);
|
||||
guiGraphics.pose().popPose();
|
||||
}
|
||||
|
||||
private Bounds buttonBounds(int rowIndex, int colIndex) {
|
||||
return new Bounds(
|
||||
this.leftPos + BUTTON_START_X + colIndex * (BUTTON_WIDTH + BUTTON_SCREEN_GAP_X),
|
||||
this.topPos + BUTTON_START_Y + rowIndex * (BUTTON_HEIGHT + BUTTON_SCREEN_GAP_Y),
|
||||
BUTTON_WIDTH,
|
||||
BUTTON_HEIGHT
|
||||
);
|
||||
}
|
||||
|
||||
private static boolean isBatteryModeToggle(int index) {
|
||||
return index == 0;
|
||||
}
|
||||
|
||||
private static int indexToRow(int index) {
|
||||
return index <= 3 ? 0 : 1;
|
||||
}
|
||||
|
||||
private static int indexToColumn(int index) {
|
||||
return switch (index) {
|
||||
case 0, 1, 4 -> 1;
|
||||
case 2, 5 -> 2;
|
||||
case 3, 6 -> 3;
|
||||
default -> 1;
|
||||
};
|
||||
}
|
||||
|
||||
private record Bounds(int x, int y, int width, int height) {
|
||||
private boolean contains(double mouseX, double mouseY) {
|
||||
return mouseX >= this.x && mouseX < this.x + this.width && mouseY >= this.y && mouseY < this.y + this.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package com.trunksbomb.batteries.v21_1.client.screen;
|
||||
|
||||
import com.trunksbomb.batteries.shared.BatteryBlockData;
|
||||
import com.trunksbomb.batteries.v21_1.block.entity.BatteryBlockEntity;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryItem;
|
||||
import com.trunksbomb.batteries.v21_1.menu.BatteryBlockMenu;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.components.Tooltip;
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
|
||||
public class BatteryBlockScreen extends AbstractContainerScreen<BatteryBlockMenu> {
|
||||
private static final ResourceLocation TEXTURE = ResourceLocation.fromNamespaceAndPath("batteries", "textures/battery_block_gui.png");
|
||||
private static final int TEXTURE_WIDTH = 176;
|
||||
private static final int TEXTURE_HEIGHT = 164;
|
||||
private static final int BUTTON_WIDTH = 50;
|
||||
private static final int BUTTON_HEIGHT = 20;
|
||||
private static final int BUTTON_START_X = 8;
|
||||
private static final int BUTTON_START_Y = 18;
|
||||
private static final int BUTTON_GAP_X = 5;
|
||||
private static final int BUTTON_GAP_Y = 4;
|
||||
|
||||
public BatteryBlockScreen(BatteryBlockMenu menu, Inventory playerInventory, Component title) {
|
||||
super(menu, playerInventory, title);
|
||||
this.imageWidth = TEXTURE_WIDTH;
|
||||
this.imageHeight = TEXTURE_HEIGHT;
|
||||
this.inventoryLabelY = this.imageHeight - 94;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
for (int index = 0; index < BatteryBlockMenu.SIDE_BUTTON_COUNT; index++) {
|
||||
int buttonIndex = index;
|
||||
this.addRenderableWidget(Button.builder(buttonLabel(index), button -> pressButton(buttonIndex))
|
||||
.bounds(this.leftPos + buttonX(index), this.topPos + buttonY(index), BUTTON_WIDTH, BUTTON_HEIGHT)
|
||||
.tooltip(buttonTooltip(index))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containerTick() {
|
||||
super.containerTick();
|
||||
int widgetIndex = 0;
|
||||
for (AbstractWidget widget : this.renderables.stream().filter(AbstractWidget.class::isInstance).map(AbstractWidget.class::cast).toList()) {
|
||||
if (widgetIndex >= BatteryBlockMenu.SIDE_BUTTON_COUNT) {
|
||||
break;
|
||||
}
|
||||
widget.setMessage(buttonLabel(widgetIndex));
|
||||
widget.setTooltip(buttonTooltip(widgetIndex));
|
||||
widgetIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY) {
|
||||
guiGraphics.blit(TEXTURE, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight, TEXTURE_WIDTH, TEXTURE_HEIGHT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderLabels(GuiGraphics guiGraphics, int mouseX, int mouseY) {
|
||||
Component title = Component.literal(this.title.getString()
|
||||
+ " - "
|
||||
+ BatteryItem.formatCompactAmount(this.menu.storedEnergy())
|
||||
+ " / "
|
||||
+ BatteryItem.formatCompactAmount(this.menu.energyCapacity())
|
||||
+ " E");
|
||||
guiGraphics.drawString(this.font, title, 8, 6, 0xFF404040, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
|
||||
this.renderBackground(guiGraphics, mouseX, mouseY, partialTick);
|
||||
super.render(guiGraphics, mouseX, mouseY, partialTick);
|
||||
this.renderTooltip(guiGraphics, mouseX, mouseY);
|
||||
}
|
||||
|
||||
private void pressButton(int index) {
|
||||
if (this.minecraft.gameMode == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.minecraft.gameMode.handleInventoryButtonClick(this.menu.containerId, index);
|
||||
this.menu.cycleClientPreview(index);
|
||||
}
|
||||
|
||||
private Component buttonLabel(int index) {
|
||||
return Component.literal(shortDirection(index) + ": " + shortMode(this.menu.sideMode(index)));
|
||||
}
|
||||
|
||||
private Tooltip buttonTooltip(int index) {
|
||||
return Tooltip.create(Component.literal(fullDirection(index) + ": " + fullMode(this.menu.sideMode(index))));
|
||||
}
|
||||
|
||||
private static int buttonX(int index) {
|
||||
return BUTTON_START_X + (index % 3) * (BUTTON_WIDTH + BUTTON_GAP_X);
|
||||
}
|
||||
|
||||
private static int buttonY(int index) {
|
||||
return BUTTON_START_Y + (index / 3) * (BUTTON_HEIGHT + BUTTON_GAP_Y);
|
||||
}
|
||||
|
||||
private static String shortDirection(int index) {
|
||||
return switch (BatteryBlockEntity.directionForIndex(index)) {
|
||||
case UP -> "U";
|
||||
case DOWN -> "D";
|
||||
case NORTH -> "N";
|
||||
case SOUTH -> "S";
|
||||
case WEST -> "W";
|
||||
case EAST -> "E";
|
||||
};
|
||||
}
|
||||
|
||||
private static String fullDirection(int index) {
|
||||
return switch (BatteryBlockEntity.directionForIndex(index)) {
|
||||
case UP -> "Up";
|
||||
case DOWN -> "Down";
|
||||
case NORTH -> "North";
|
||||
case SOUTH -> "South";
|
||||
case WEST -> "West";
|
||||
case EAST -> "East";
|
||||
};
|
||||
}
|
||||
|
||||
private static String shortMode(BatteryBlockData.SideMode mode) {
|
||||
return switch (mode) {
|
||||
case INPUT -> "In";
|
||||
case OUTPUT -> "Out";
|
||||
case BOTH -> "Both";
|
||||
case NONE -> "None";
|
||||
};
|
||||
}
|
||||
|
||||
private static String fullMode(BatteryBlockData.SideMode mode) {
|
||||
return switch (mode) {
|
||||
case INPUT -> "Input";
|
||||
case OUTPUT -> "Output";
|
||||
case BOTH -> "Both";
|
||||
case NONE -> "None";
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.trunksbomb.batteries.v21_1.client.screen;
|
||||
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryItem;
|
||||
import com.trunksbomb.batteries.v21_1.menu.CoalGeneratorMenu;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
|
||||
public class CoalGeneratorScreen extends AbstractContainerScreen<CoalGeneratorMenu> {
|
||||
private static final ResourceLocation TEXTURE = ResourceLocation.fromNamespaceAndPath("batteries", "textures/coal_generator_gui.png");
|
||||
private static final int FLAME_X = 81;
|
||||
private static final int FLAME_Y = 61;
|
||||
private static final int FLAME_WIDTH = 14;
|
||||
private static final int FLAME_HEIGHT = 14;
|
||||
private static final int FLAME_BORDER = 0xFF3A2A17;
|
||||
private static final int FLAME_BG = 0xFF5B4A2C;
|
||||
private static final int FLAME_FILL = 0xFFFFB347;
|
||||
private static final int FLAME_CORE = 0xFFFFE08A;
|
||||
|
||||
public CoalGeneratorScreen(CoalGeneratorMenu menu, Inventory playerInventory, Component title) {
|
||||
super(menu, playerInventory, title);
|
||||
this.imageWidth = 176;
|
||||
this.imageHeight = 164;
|
||||
this.inventoryLabelY = this.imageHeight - 94;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY) {
|
||||
guiGraphics.blit(TEXTURE, this.leftPos, this.topPos, 0, 0, this.imageWidth, this.imageHeight, this.imageWidth, this.imageHeight);
|
||||
this.renderFlame(guiGraphics);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderLabels(GuiGraphics guiGraphics, int mouseX, int mouseY) {
|
||||
Component title = Component.literal(this.title.getString()
|
||||
+ " - "
|
||||
+ BatteryItem.formatCompactAmount(this.menu.storedEnergy())
|
||||
+ " / "
|
||||
+ BatteryItem.formatCompactAmount(this.menu.energyCapacity())
|
||||
+ " E");
|
||||
guiGraphics.drawString(this.font, title, 8, 6, 0xFF404040, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
|
||||
this.renderBackground(guiGraphics, mouseX, mouseY, partialTick);
|
||||
super.render(guiGraphics, mouseX, mouseY, partialTick);
|
||||
this.renderTooltip(guiGraphics, mouseX, mouseY);
|
||||
}
|
||||
|
||||
private void renderFlame(GuiGraphics guiGraphics) {
|
||||
int maxBurn = this.menu.maxBurnTime();
|
||||
int burn = this.menu.burnTimeRemaining();
|
||||
int x = this.leftPos + FLAME_X;
|
||||
int y = this.topPos + FLAME_Y;
|
||||
|
||||
guiGraphics.fill(x, y, x + FLAME_WIDTH, y + FLAME_HEIGHT, FLAME_BORDER);
|
||||
guiGraphics.fill(x + 1, y + 1, x + FLAME_WIDTH - 1, y + FLAME_HEIGHT - 1, FLAME_BG);
|
||||
|
||||
if (maxBurn <= 0 || burn <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int flameHeight = Math.max(1, burn * (FLAME_HEIGHT - 2) / maxBurn);
|
||||
int top = y + FLAME_HEIGHT - 1 - flameHeight;
|
||||
guiGraphics.fill(x + 2, top, x + FLAME_WIDTH - 2, y + FLAME_HEIGHT - 2, FLAME_FILL);
|
||||
guiGraphics.fill(x + 4, Math.max(y + 2, top + 2), x + FLAME_WIDTH - 4, y + FLAME_HEIGHT - 4, FLAME_CORE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.trunksbomb.batteries.v21_1.integration.jei;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesNeoForge121;
|
||||
import java.util.List;
|
||||
import mezz.jei.api.IModPlugin;
|
||||
import mezz.jei.api.JeiPlugin;
|
||||
import mezz.jei.api.constants.RecipeTypes;
|
||||
import mezz.jei.api.recipe.vanilla.IVanillaRecipeFactory;
|
||||
import mezz.jei.api.registration.IRecipeRegistration;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
||||
import net.minecraft.world.item.crafting.CraftingRecipe;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.item.crafting.RecipeHolder;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
|
||||
@JeiPlugin
|
||||
public class BatteriesJeiPlugin implements IModPlugin {
|
||||
private static final ResourceLocation PLUGIN_UID = ResourceLocation.fromNamespaceAndPath(BatteriesNeoForge121.MODID, "jei_plugin");
|
||||
|
||||
@Override
|
||||
public @NonNull ResourceLocation getPluginUid() {
|
||||
return PLUGIN_UID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerRecipes(IRecipeRegistration registration) {
|
||||
IVanillaRecipeFactory recipeFactory = registration.getVanillaRecipeFactory();
|
||||
registration.addRecipes(RecipeTypes.CRAFTING, List.of(
|
||||
twoItemRecipe("battery_pickaxe", recipeFactory, BatteriesNeoForge121.BATTERY_PICKAXE.get(), CraftingBookCategory.EQUIPMENT, Items.DIAMOND_PICKAXE, BatteriesNeoForge121.BATTERY.get()),
|
||||
twoItemRecipe("battery_axe", recipeFactory, BatteriesNeoForge121.BATTERY_AXE.get(), CraftingBookCategory.EQUIPMENT, Items.DIAMOND_AXE, BatteriesNeoForge121.BATTERY.get()),
|
||||
twoItemRecipe("battery_shovel", recipeFactory, BatteriesNeoForge121.BATTERY_SHOVEL.get(), CraftingBookCategory.EQUIPMENT, Items.DIAMOND_SHOVEL, BatteriesNeoForge121.BATTERY.get()),
|
||||
twoItemRecipe("battery_hoe", recipeFactory, BatteriesNeoForge121.BATTERY_HOE.get(), CraftingBookCategory.EQUIPMENT, Items.DIAMOND_HOE, BatteriesNeoForge121.BATTERY.get()),
|
||||
twoItemRecipe("battery_sword", recipeFactory, BatteriesNeoForge121.BATTERY_SWORD.get(), CraftingBookCategory.EQUIPMENT, Items.DIAMOND_SWORD, BatteriesNeoForge121.BATTERY.get()),
|
||||
twoItemRecipe("battery_helmet", recipeFactory, BatteriesNeoForge121.BATTERY_HELMET.get(), CraftingBookCategory.EQUIPMENT, Items.DIAMOND_HELMET, BatteriesNeoForge121.BATTERY.get()),
|
||||
twoItemRecipe("battery_chestplate", recipeFactory, BatteriesNeoForge121.BATTERY_CHESTPLATE.get(), CraftingBookCategory.EQUIPMENT, Items.DIAMOND_CHESTPLATE, BatteriesNeoForge121.BATTERY.get()),
|
||||
twoItemRecipe("battery_leggings", recipeFactory, BatteriesNeoForge121.BATTERY_LEGGINGS.get(), CraftingBookCategory.EQUIPMENT, Items.DIAMOND_LEGGINGS, BatteriesNeoForge121.BATTERY.get()),
|
||||
twoItemRecipe("battery_boots", recipeFactory, BatteriesNeoForge121.BATTERY_BOOTS.get(), CraftingBookCategory.EQUIPMENT, Items.DIAMOND_BOOTS, BatteriesNeoForge121.BATTERY.get()),
|
||||
twoItemRecipe("battery_shield", recipeFactory, BatteriesNeoForge121.BATTERY_SHIELD.get(), CraftingBookCategory.EQUIPMENT, Items.SHIELD, BatteriesNeoForge121.BATTERY.get()),
|
||||
twoItemRecipe("battery_bow", recipeFactory, BatteriesNeoForge121.BATTERY_BOW.get(), CraftingBookCategory.EQUIPMENT, Items.BOW, BatteriesNeoForge121.BATTERY.get()),
|
||||
recipe("battery1_upgrade", recipeFactory, BatteriesNeoForge121.BATTERY1.get(), Items.REDSTONE, Items.GOLD_BLOCK, BatteriesNeoForge121.BATTERY.get(), Items.REDSTONE_BLOCK),
|
||||
recipe("battery2_upgrade", recipeFactory, BatteriesNeoForge121.BATTERY2.get(), Items.REDSTONE, Items.DIAMOND, BatteriesNeoForge121.BATTERY1.get(), Items.REDSTONE_BLOCK),
|
||||
recipe("battery3_upgrade", recipeFactory, BatteriesNeoForge121.BATTERY3.get(), Items.REDSTONE, Items.DIAMOND_BLOCK, BatteriesNeoForge121.BATTERY2.get(), Items.REDSTONE_BLOCK),
|
||||
recipe("battery_ender_upgrade", recipeFactory, BatteriesNeoForge121.BATTERY_ENDER.get(), Items.END_STONE, Items.DIAMOND_BLOCK, BatteriesNeoForge121.BATTERY3.get(), Items.ENDER_PEARL)
|
||||
));
|
||||
}
|
||||
|
||||
private static RecipeHolder<CraftingRecipe> recipe(String name, IVanillaRecipeFactory recipeFactory, ItemLike result,
|
||||
ItemLike corner, ItemLike topBottom, ItemLike center, ItemLike middleSide) {
|
||||
CraftingRecipe recipe = recipeFactory.createShapedRecipeBuilder(CraftingBookCategory.REDSTONE, List.of(new ItemStack(result)))
|
||||
.define('r', Ingredient.of(corner))
|
||||
.define('g', Ingredient.of(topBottom))
|
||||
.define('i', Ingredient.of(center))
|
||||
.define('b', Ingredient.of(middleSide))
|
||||
.pattern("rgr")
|
||||
.pattern("bib")
|
||||
.pattern("rgr")
|
||||
.build();
|
||||
ResourceLocation recipeId = ResourceLocation.fromNamespaceAndPath(BatteriesNeoForge121.MODID, "jei/" + name);
|
||||
return new RecipeHolder<>(recipeId, recipe);
|
||||
}
|
||||
|
||||
private static RecipeHolder<CraftingRecipe> twoItemRecipe(String name, IVanillaRecipeFactory recipeFactory, ItemLike result,
|
||||
CraftingBookCategory category, ItemLike first, ItemLike second) {
|
||||
CraftingRecipe recipe = recipeFactory.createShapedRecipeBuilder(category, List.of(new ItemStack(result)))
|
||||
.define('a', Ingredient.of(first))
|
||||
.define('b', Ingredient.of(second))
|
||||
.pattern("ab")
|
||||
.build();
|
||||
ResourceLocation recipeId = ResourceLocation.fromNamespaceAndPath(BatteriesNeoForge121.MODID, "jei/" + name);
|
||||
return new RecipeHolder<>(recipeId, recipe);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.trunksbomb.batteries.v21_1.item;
|
||||
|
||||
import com.trunksbomb.batteries.item.BatteryItemData;
|
||||
import java.util.List;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class BatteryBlockItem extends BlockItem {
|
||||
public static final int BASE_CAPACITY = 50_000;
|
||||
private static final String ENERGY_KEY = "energy";
|
||||
private static final String CAPACITY_KEY = "capacity";
|
||||
|
||||
public BatteryBlockItem(Block block, Item.Properties properties) {
|
||||
super(block, properties.stacksTo(1));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static IEnergyStorage createEnergyHandler(ItemStack stack) {
|
||||
initializeDefaults(stack);
|
||||
return new BatteryBlockItemEnergyStorage(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBarVisible(ItemStack stack) {
|
||||
return getEnergyCapacity(stack) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBarWidth(ItemStack stack) {
|
||||
int capacity = getEnergyCapacity(stack);
|
||||
return capacity <= 0 ? 0 : Math.round(13.0F * getStoredEnergy(stack) / (float) capacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBarColor(ItemStack stack) {
|
||||
return 0x55CC55;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltip, TooltipFlag flag) {
|
||||
tooltip.add(Component.translatable(
|
||||
"batteries.tooltip.energy",
|
||||
BatteryItemData.formatCompactAmount(getStoredEnergy(stack)),
|
||||
BatteryItemData.formatCompactAmount(getEnergyCapacity(stack)))
|
||||
.withStyle(ChatFormatting.GREEN));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
|
||||
return slotChanged || !newStack.is(oldStack.getItem());
|
||||
}
|
||||
|
||||
public static void initializeDefaults(ItemStack stack) {
|
||||
if (getRawCapacity(stack) <= 0) {
|
||||
setEnergyCapacity(stack, BASE_CAPACITY);
|
||||
setStoredEnergy(stack, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static int getEnergyCapacity(ItemStack stack) {
|
||||
int capacity = getRawCapacity(stack);
|
||||
return capacity > 0 ? capacity : BASE_CAPACITY;
|
||||
}
|
||||
|
||||
public static int getStoredEnergy(ItemStack stack) {
|
||||
CompoundTag tag = stack.getOrDefault(DataComponents.CUSTOM_DATA, net.minecraft.world.item.component.CustomData.EMPTY).copyTag();
|
||||
int energy = tag.contains(ENERGY_KEY) ? tag.getInt(ENERGY_KEY) : 0;
|
||||
return Math.max(0, Math.min(energy, getEnergyCapacity(stack)));
|
||||
}
|
||||
|
||||
public static void setStoredEnergy(ItemStack stack, int energy) {
|
||||
int clamped = Math.max(0, Math.min(energy, getEnergyCapacity(stack)));
|
||||
net.minecraft.world.item.component.CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> tag.putInt(ENERGY_KEY, clamped));
|
||||
}
|
||||
|
||||
public static void setEnergyCapacity(ItemStack stack, int capacity) {
|
||||
int clampedCapacity = Math.max(BASE_CAPACITY, capacity);
|
||||
net.minecraft.world.item.component.CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> {
|
||||
tag.putInt(CAPACITY_KEY, clampedCapacity);
|
||||
int existing = tag.contains(ENERGY_KEY) ? tag.getInt(ENERGY_KEY) : 0;
|
||||
tag.putInt(ENERGY_KEY, Math.max(0, Math.min(existing, clampedCapacity)));
|
||||
});
|
||||
}
|
||||
|
||||
public static int getMaxTransfer(ItemStack stack) {
|
||||
return com.trunksbomb.batteries.item.EnergyTierHelper.transferRateForCapacity(getEnergyCapacity(stack));
|
||||
}
|
||||
|
||||
private static int getRawCapacity(ItemStack stack) {
|
||||
CompoundTag tag = stack.getOrDefault(DataComponents.CUSTOM_DATA, net.minecraft.world.item.component.CustomData.EMPTY).copyTag();
|
||||
return tag.contains(CAPACITY_KEY) ? tag.getInt(CAPACITY_KEY) : 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.trunksbomb.batteries.v21_1.item;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.neoforged.neoforge.energy.EnergyStorage;
|
||||
|
||||
final class BatteryBlockItemEnergyStorage extends EnergyStorage {
|
||||
private final ItemStack stack;
|
||||
|
||||
BatteryBlockItemEnergyStorage(ItemStack stack) {
|
||||
super(BatteryBlockItem.getEnergyCapacity(stack), BatteryBlockItem.getMaxTransfer(stack), BatteryBlockItem.getMaxTransfer(stack), BatteryBlockItem.getStoredEnergy(stack));
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int receiveEnergy(int maxReceive, boolean simulate) {
|
||||
int received = super.receiveEnergy(maxReceive, simulate);
|
||||
if (!simulate && received > 0) {
|
||||
BatteryBlockItem.setStoredEnergy(this.stack, this.energy);
|
||||
}
|
||||
return received;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||
int extracted = super.extractEnergy(maxExtract, simulate);
|
||||
if (!simulate && extracted > 0) {
|
||||
BatteryBlockItem.setStoredEnergy(this.stack, this.energy);
|
||||
}
|
||||
return extracted;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.trunksbomb.batteries.v21_1.item;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.neoforged.neoforge.energy.EnergyStorage;
|
||||
|
||||
final class BatteryEnergyHandler extends EnergyStorage {
|
||||
private final ItemStack stack;
|
||||
private final boolean creative;
|
||||
|
||||
BatteryEnergyHandler(ItemStack stack, int capacity, int maxTransfer, int energy, boolean creative) {
|
||||
super(capacity, maxTransfer, maxTransfer, creative ? capacity : energy);
|
||||
this.stack = stack;
|
||||
this.creative = creative;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int receiveEnergy(int maxReceive, boolean simulate) {
|
||||
if (this.creative) {
|
||||
return maxReceive;
|
||||
}
|
||||
|
||||
int received = super.receiveEnergy(maxReceive, simulate);
|
||||
if (!simulate && received > 0) {
|
||||
BatteryItem.setStoredEnergy(this.stack, this.energy);
|
||||
}
|
||||
return received;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||
if (this.creative) {
|
||||
return maxExtract;
|
||||
}
|
||||
|
||||
int extracted = super.extractEnergy(maxExtract, simulate);
|
||||
if (!simulate && extracted > 0) {
|
||||
BatteryItem.setStoredEnergy(this.stack, this.energy);
|
||||
}
|
||||
return extracted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnergyStored() {
|
||||
return this.creative ? this.capacity : super.getEnergyStored();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
package com.trunksbomb.batteries.v21_1.item;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesConfig;
|
||||
import com.trunksbomb.batteries.item.BatteryItemData;
|
||||
import com.trunksbomb.batteries.item.BatteryItemData.Tier;
|
||||
import com.trunksbomb.batteries.v21_1.menu.BatteriesMenu;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.MenuProvider;
|
||||
import net.minecraft.world.SimpleMenuProvider;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.item.component.CustomData;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.neoforged.neoforge.capabilities.Capabilities;
|
||||
import net.neoforged.neoforge.energy.IEnergyStorage;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class BatteryItem extends Item {
|
||||
private static final String BATTERY_UUID_KEY = "battery_uuid";
|
||||
private static final String WHITELIST_KEY = "whitelist";
|
||||
private static final String CHARGE_HOTBAR_KEY = "charge_hotbar";
|
||||
private static final String CHARGE_INVENTORY_KEY = "charge_inventory";
|
||||
private static final String CHARGE_ARMOR_KEY = "charge_armor";
|
||||
private static final String CHARGE_FAIRLY_KEY = "charge_fairly";
|
||||
private static final String CHARGE_MACHINE_KEY = "charge_machine";
|
||||
private static final String FILTER_SLOT_KEY_PREFIX = "filter_slot_";
|
||||
|
||||
private final Tier tier;
|
||||
|
||||
public BatteryItem(Tier tier, Properties properties) {
|
||||
super(properties.stacksTo(1));
|
||||
this.tier = tier;
|
||||
}
|
||||
|
||||
public Tier tier() {
|
||||
return this.tier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult useOn(UseOnContext context) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand usedHand) {
|
||||
if (player instanceof ServerPlayer serverPlayer) {
|
||||
ItemStack stack = player.getItemInHand(usedHand);
|
||||
MenuProvider provider = new SimpleMenuProvider(
|
||||
(containerId, inventory, menuPlayer) -> BatteriesMenu.forBattery(containerId, inventory, usedHand),
|
||||
stack.getHoverName()
|
||||
);
|
||||
serverPlayer.openMenu(provider, buffer -> BatteriesMenu.writeBatteryMenu(buffer, usedHand));
|
||||
}
|
||||
|
||||
return InteractionResultHolder.success(player.getItemInHand(usedHand));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotId, boolean isSelected) {
|
||||
if (!(level instanceof ServerLevel serverLevel) || !(entity instanceof ServerPlayer player) || !(stack.getItem() instanceof BatteryItem batteryItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (batteryItem.tier != Tier.CREATIVE && getStoredEnergy(stack) <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isChargeHotbarEnabled(stack)) {
|
||||
for (int i = 0; i < 9; i++) {
|
||||
chargeItemIfValid(stack, player.getInventory().getItem(i));
|
||||
}
|
||||
}
|
||||
|
||||
if (isChargeInventoryEnabled(stack)) {
|
||||
for (int i = 9; i < 36; i++) {
|
||||
chargeItemIfValid(stack, player.getInventory().getItem(i));
|
||||
}
|
||||
}
|
||||
|
||||
if (isChargeWornEnabled(stack)) {
|
||||
for (int i = 36; i <= 40; i++) {
|
||||
chargeItemIfValid(stack, player.getInventory().getItem(i));
|
||||
}
|
||||
}
|
||||
|
||||
if (isChargeMachineEnabled(stack)) {
|
||||
chargeNearbyMachines(stack, player, serverLevel);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
|
||||
return slotChanged || !newStack.is(oldStack.getItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBarVisible(ItemStack stack) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBarWidth(ItemStack stack) {
|
||||
int capacity = getEnergyCapacity(stack);
|
||||
if (capacity <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Math.round(13.0F * getStoredEnergy(stack) / (float) capacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBarColor(ItemStack stack) {
|
||||
return 0x55CC55;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHoverText(ItemStack stack, Item.TooltipContext context, List<Component> tooltipAdder, TooltipFlag flag) {
|
||||
tooltipAdder.add(Component.translatable(
|
||||
"batteries.tooltip.energy",
|
||||
formatCompactAmount(getStoredEnergy(stack)),
|
||||
formatCompactAmount(getEnergyCapacity(stack)))
|
||||
.withStyle(ChatFormatting.GREEN));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static IEnergyStorage createEnergyHandler(ItemStack stack) {
|
||||
if (!(stack.getItem() instanceof BatteryItem batteryItem)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int capacity = BatteryItemData.getEnergyCapacity(batteryItem.tier);
|
||||
int maxTransfer = BatteryItemData.getMaxTransfer(batteryItem.tier);
|
||||
return new BatteryEnergyHandler(stack, capacity, maxTransfer, getStoredEnergy(stack), batteryItem.tier == Tier.CREATIVE);
|
||||
}
|
||||
|
||||
public static int getStoredEnergy(ItemStack stack) {
|
||||
if (stack.getItem() instanceof BatteryItem batteryItem) {
|
||||
return BatteryItemData.getStoredEnergy(stack, batteryItem.tier);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setStoredEnergy(ItemStack stack, int energy) {
|
||||
BatteryItemData.setStoredEnergy(stack, energy);
|
||||
}
|
||||
|
||||
public static int getEnergyCapacity(ItemStack stack) {
|
||||
if (stack.getItem() instanceof BatteryItem batteryItem) {
|
||||
return BatteryItemData.getEnergyCapacity(batteryItem.tier);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int getMaxTransfer(ItemStack stack) {
|
||||
if (stack.getItem() instanceof BatteryItem batteryItem) {
|
||||
return BatteryItemData.getMaxTransfer(batteryItem.tier);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static UUID ensureBatteryId(ItemStack stack) {
|
||||
CompoundTag tag = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
|
||||
String existingUuid = tag.getString(BATTERY_UUID_KEY);
|
||||
if (!existingUuid.isBlank()) {
|
||||
return UUID.fromString(existingUuid);
|
||||
}
|
||||
|
||||
UUID uuid = UUID.randomUUID();
|
||||
CustomData.update(DataComponents.CUSTOM_DATA, stack, data -> data.putString(BATTERY_UUID_KEY, uuid.toString()));
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static UUID getBatteryId(ItemStack stack) {
|
||||
CompoundTag tag = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
|
||||
String uuid = tag.getString(BATTERY_UUID_KEY);
|
||||
return uuid.isBlank() ? null : UUID.fromString(uuid);
|
||||
}
|
||||
|
||||
public static ItemStack findLinkedEnderBattery(Player player, UUID batteryId) {
|
||||
if (batteryId == null) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
for (int slot = 0; slot < player.getInventory().getContainerSize(); slot++) {
|
||||
ItemStack stack = player.getInventory().getItem(slot);
|
||||
if (!(stack.getItem() instanceof BatteryItem batteryItem) || batteryItem.tier() != Tier.ENDER) {
|
||||
continue;
|
||||
}
|
||||
|
||||
UUID stackId = getBatteryId(stack);
|
||||
if (batteryId.equals(stackId)) {
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
private static void chargeItemIfValid(ItemStack battery, ItemStack receivingStack) {
|
||||
if (receivingStack.isEmpty() || receivingStack == battery || receivingStack.getItem() instanceof BatteryItem || !matchesFilter(battery, receivingStack)) {
|
||||
return;
|
||||
}
|
||||
|
||||
IEnergyStorage receivingEnergy = receivingStack.getCapability(Capabilities.EnergyStorage.ITEM);
|
||||
if (receivingEnergy == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
transferEnergyToTarget(battery, receivingEnergy, isFairChargingEnabled(battery));
|
||||
}
|
||||
|
||||
private static void chargeNearbyMachines(ItemStack battery, ServerPlayer player, ServerLevel level) {
|
||||
int range = BatteriesConfig.machineChargeRange();
|
||||
BlockPos center = player.blockPosition();
|
||||
boolean fairCharging = isFairChargingEnabled(battery);
|
||||
|
||||
for (BlockPos pos : BlockPos.betweenClosed(center.offset(-range, -range, -range), center.offset(range, range, range))) {
|
||||
if (!level.isLoaded(pos)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Direction side = getFacingFromBlockToPlayer(player, pos);
|
||||
IEnergyStorage energyHandler = level.getCapability(Capabilities.EnergyStorage.BLOCK, pos.immutable(), side);
|
||||
if (energyHandler == null || !energyHandler.canReceive()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
transferEnergyToTarget(battery, energyHandler, fairCharging);
|
||||
if (((BatteryItem) battery.getItem()).tier != Tier.CREATIVE && getStoredEnergy(battery) <= 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Direction getFacingFromBlockToPlayer(Player player, BlockPos pos) {
|
||||
double dx = player.getX() - (pos.getX() + 0.5D);
|
||||
double dy = player.getEyeY() - (pos.getY() + 0.5D);
|
||||
double dz = player.getZ() - (pos.getZ() + 0.5D);
|
||||
double absX = Math.abs(dx);
|
||||
double absY = Math.abs(dy);
|
||||
double absZ = Math.abs(dz);
|
||||
if (absY >= absX && absY >= absZ) {
|
||||
return dy >= 0.0D ? Direction.UP : Direction.DOWN;
|
||||
}
|
||||
if (absX >= absZ) {
|
||||
return dx >= 0.0D ? Direction.EAST : Direction.WEST;
|
||||
}
|
||||
return dz >= 0.0D ? Direction.SOUTH : Direction.NORTH;
|
||||
}
|
||||
|
||||
private static void transferEnergyToTarget(ItemStack battery, IEnergyStorage target, boolean fairCharging) {
|
||||
IEnergyStorage batteryEnergy = createEnergyHandler(battery);
|
||||
if (batteryEnergy == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int targetStored = target.getEnergyStored();
|
||||
int targetCapacity = target.getMaxEnergyStored();
|
||||
if (targetCapacity <= targetStored) {
|
||||
return;
|
||||
}
|
||||
|
||||
int batteryStored = getStoredEnergy(battery);
|
||||
if (fairCharging && batteryStored <= targetStored) {
|
||||
return;
|
||||
}
|
||||
|
||||
int transferLimit = Math.min(getMaxTransfer(battery), targetCapacity - targetStored);
|
||||
if (transferLimit <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (((BatteryItem) battery.getItem()).tier == Tier.CREATIVE) {
|
||||
target.receiveEnergy(transferLimit, false);
|
||||
return;
|
||||
}
|
||||
|
||||
int accepted = target.receiveEnergy(transferLimit, true);
|
||||
if (accepted <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int extracted = batteryEnergy.extractEnergy(accepted, false);
|
||||
if (extracted <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
target.receiveEnergy(extracted, false);
|
||||
}
|
||||
|
||||
private static boolean matchesFilter(ItemStack battery, ItemStack candidate) {
|
||||
CompoundTag tag = battery.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
|
||||
boolean whitelist = tag.getBoolean(WHITELIST_KEY);
|
||||
boolean hasFilterEntries = false;
|
||||
boolean matched = false;
|
||||
|
||||
for (int i = 0; i < BatteriesMenu.FILTER_SLOT_COUNT; i++) {
|
||||
String itemId = tag.getString(filterSlotKey(i));
|
||||
if (itemId.isBlank()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
hasFilterEntries = true;
|
||||
Item item = BuiltInRegistries.ITEM.get(ResourceLocation.parse(itemId));
|
||||
if (candidate.is(item)) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasFilterEntries) {
|
||||
return !whitelist;
|
||||
}
|
||||
|
||||
return whitelist == matched;
|
||||
}
|
||||
|
||||
private static boolean isChargeHotbarEnabled(ItemStack stack) {
|
||||
return getToggle(stack, CHARGE_HOTBAR_KEY);
|
||||
}
|
||||
|
||||
private static boolean isChargeInventoryEnabled(ItemStack stack) {
|
||||
return getToggle(stack, CHARGE_INVENTORY_KEY);
|
||||
}
|
||||
|
||||
private static boolean isChargeWornEnabled(ItemStack stack) {
|
||||
return getToggle(stack, CHARGE_ARMOR_KEY);
|
||||
}
|
||||
|
||||
private static boolean isFairChargingEnabled(ItemStack stack) {
|
||||
return getToggle(stack, CHARGE_FAIRLY_KEY);
|
||||
}
|
||||
|
||||
private static boolean isChargeMachineEnabled(ItemStack stack) {
|
||||
return getToggle(stack, CHARGE_MACHINE_KEY);
|
||||
}
|
||||
|
||||
private static boolean getToggle(ItemStack stack, String key) {
|
||||
CompoundTag tag = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
|
||||
return tag.getBoolean(key);
|
||||
}
|
||||
|
||||
private static String filterSlotKey(int index) {
|
||||
return FILTER_SLOT_KEY_PREFIX + index;
|
||||
}
|
||||
|
||||
public static String formatWithCommas(int amount) {
|
||||
return BatteryItemData.formatWithCommas(amount);
|
||||
}
|
||||
|
||||
public static String formatCompactAmount(int amount) {
|
||||
return BatteryItemData.formatCompactAmount(amount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.trunksbomb.batteries.v21_1.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.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.ArmorItem;
|
||||
import net.minecraft.world.item.ArmorMaterial;
|
||||
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 org.jspecify.annotations.Nullable;
|
||||
|
||||
public class BatteryPoweredArmorItem extends ArmorItem implements PoweredItem {
|
||||
private final ArmorItem.Type armorType;
|
||||
|
||||
public BatteryPoweredArmorItem(Holder<ArmorMaterial> material, ArmorItem.Type armorType, Item.Properties properties) {
|
||||
super(material, armorType, properties.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, Item.TooltipContext context, List<Component> tooltipAdder, TooltipFlag flag) {
|
||||
this.addEnergyTooltip(stack, tooltipAdder::add, flag);
|
||||
}
|
||||
|
||||
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 boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
|
||||
return this.shouldCauseEnergyReequipAnimation(oldStack, newStack, slotChanged);
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.trunksbomb.batteries.v21_1.item;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesConfig;
|
||||
import java.util.List;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.AxeItem;
|
||||
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.Tiers;
|
||||
import net.minecraft.world.item.enchantment.Enchantment;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class BatteryPoweredAxeItem extends AxeItem implements PoweredItem {
|
||||
public BatteryPoweredAxeItem(Item.Properties properties) {
|
||||
super(Tiers.DIAMOND, 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, Item.TooltipContext context, List<Component> tooltipAdder, TooltipFlag flag) {
|
||||
this.addEnergyTooltip(stack, tooltipAdder::add, flag);
|
||||
}
|
||||
|
||||
public ItemStack getEnchantingBaseStack(ItemStack stack) {
|
||||
return new ItemStack(Items.DIAMOND_AXE);
|
||||
}
|
||||
|
||||
@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, net.minecraft.core.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, T entity, java.util.function.Consumer<Item> onBroken) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int energyCost(ItemStack stack) {
|
||||
return this.getAdjustedEnergyCost(stack, BatteriesConfig.axeEnergyPerBlock());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.trunksbomb.batteries.v21_1.item;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesConfig;
|
||||
import java.util.List;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.InteractionResultHolder;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
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;
|
||||
|
||||
public class BatteryPoweredBowItem extends BowItem implements PoweredItem {
|
||||
public BatteryPoweredBowItem(Item.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, Item.TooltipContext context, List<Component> tooltipAdder, TooltipFlag flag) {
|
||||
this.addEnergyTooltip(stack, tooltipAdder::add, flag);
|
||||
}
|
||||
|
||||
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 boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
|
||||
return this.shouldCauseEnergyReequipAnimation(oldStack, newStack, slotChanged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand usedHand) {
|
||||
ItemStack stack = player.getItemInHand(usedHand);
|
||||
if (!PoweredItemEnergy.hasEnergy(stack, 1)) {
|
||||
return InteractionResultHolder.fail(stack);
|
||||
}
|
||||
return super.use(level, player, usedHand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseUsing(ItemStack stack, Level level, LivingEntity livingEntity, int timeLeft) {
|
||||
if (!(livingEntity instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack projectile = player.getProjectile(stack);
|
||||
if (projectile.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int charge = this.getUseDuration(stack, livingEntity) - timeLeft;
|
||||
charge = net.neoforged.neoforge.event.EventHooks.onArrowLoose(stack, level, player, charge, !projectile.isEmpty());
|
||||
if (charge < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
float power = BowItem.getPowerForTime(charge);
|
||||
if (power < 0.1F) {
|
||||
return;
|
||||
}
|
||||
|
||||
int baseEnergyCost = Math.max(1, Math.round(BatteriesConfig.bowFullyChargedShotCost() * power));
|
||||
int energyCost = this.getAdjustedEnergyCost(stack, baseEnergyCost);
|
||||
if (!PoweredItemEnergy.hasEnergy(stack, energyCost)) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.releaseUsing(stack, level, livingEntity, timeLeft);
|
||||
if (!level.isClientSide()) {
|
||||
PoweredItemEnergy.consumeEnergy(stack, energyCost);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends LivingEntity> int damageItem(ItemStack stack, int amount, T entity, java.util.function.Consumer<Item> onBroken) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.trunksbomb.batteries.v21_1.item;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesConfig;
|
||||
import java.util.List;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.HoeItem;
|
||||
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.Tiers;
|
||||
import net.minecraft.world.item.enchantment.Enchantment;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class BatteryPoweredHoeItem extends HoeItem implements PoweredItem {
|
||||
public BatteryPoweredHoeItem(Item.Properties properties) {
|
||||
super(Tiers.DIAMOND, 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, Item.TooltipContext context, List<Component> tooltipAdder, TooltipFlag flag) {
|
||||
this.addEnergyTooltip(stack, tooltipAdder::add, flag);
|
||||
}
|
||||
|
||||
public ItemStack getEnchantingBaseStack(ItemStack stack) {
|
||||
return new ItemStack(Items.DIAMOND_HOE);
|
||||
}
|
||||
|
||||
@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, net.minecraft.core.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, T entity, java.util.function.Consumer<Item> onBroken) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int energyCost(ItemStack stack) {
|
||||
return this.getAdjustedEnergyCost(stack, BatteriesConfig.hoeEnergyPerBlock());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.trunksbomb.batteries.v21_1.item;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesConfig;
|
||||
import java.util.List;
|
||||
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.PickaxeItem;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.item.Tiers;
|
||||
import net.minecraft.world.item.enchantment.Enchantment;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class BatteryPoweredPickaxeItem extends PickaxeItem implements PoweredItem {
|
||||
public BatteryPoweredPickaxeItem(Item.Properties properties) {
|
||||
super(Tiers.DIAMOND, 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, Item.TooltipContext context, List<Component> tooltipAdder, TooltipFlag flag) {
|
||||
this.addEnergyTooltip(stack, tooltipAdder::add, flag);
|
||||
}
|
||||
|
||||
public ItemStack getEnchantingBaseStack(ItemStack stack) {
|
||||
return new ItemStack(Items.DIAMOND_PICKAXE);
|
||||
}
|
||||
|
||||
@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, net.minecraft.core.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, T entity, java.util.function.Consumer<Item> onBroken) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int energyCost(ItemStack stack) {
|
||||
return this.getAdjustedEnergyCost(stack, BatteriesConfig.pickaxeEnergyPerBlock());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.trunksbomb.batteries.v21_1.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.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(Item.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, Item.TooltipContext context, List<Component> tooltipAdder, TooltipFlag flag) {
|
||||
this.addEnergyTooltip(stack, tooltipAdder::add, flag);
|
||||
}
|
||||
|
||||
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 boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) {
|
||||
return this.shouldCauseEnergyReequipAnimation(oldStack, newStack, slotChanged);
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.trunksbomb.batteries.v21_1.item;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesConfig;
|
||||
import java.util.List;
|
||||
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.ShovelItem;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.item.Tiers;
|
||||
import net.minecraft.world.item.enchantment.Enchantment;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
public class BatteryPoweredShovelItem extends ShovelItem implements PoweredItem {
|
||||
public BatteryPoweredShovelItem(Item.Properties properties) {
|
||||
super(Tiers.DIAMOND, 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, Item.TooltipContext context, List<Component> tooltipAdder, TooltipFlag flag) {
|
||||
this.addEnergyTooltip(stack, tooltipAdder::add, flag);
|
||||
}
|
||||
|
||||
public ItemStack getEnchantingBaseStack(ItemStack stack) {
|
||||
return new ItemStack(Items.DIAMOND_SHOVEL);
|
||||
}
|
||||
|
||||
@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, net.minecraft.core.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, T entity, java.util.function.Consumer<Item> onBroken) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int energyCost(ItemStack stack) {
|
||||
return this.getAdjustedEnergyCost(stack, BatteriesConfig.shovelEnergyPerBlock());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.trunksbomb.batteries.v21_1.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.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.SwordItem;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.item.Tiers;
|
||||
import net.minecraft.world.item.enchantment.Enchantment;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class BatteryPoweredSwordItem extends SwordItem implements PoweredItem {
|
||||
public BatteryPoweredSwordItem(Item.Properties properties) {
|
||||
super(Tiers.DIAMOND, 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, Item.TooltipContext context, List<Component> tooltipAdder, TooltipFlag flag) {
|
||||
this.addEnergyTooltip(stack, tooltipAdder::add, flag);
|
||||
}
|
||||
|
||||
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 hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) {
|
||||
if (!attacker.level().isClientSide()) {
|
||||
PoweredItemEnergy.consumeEnergy(stack, this.energyCost(stack));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) {
|
||||
}
|
||||
|
||||
@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());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.trunksbomb.batteries.v21_1.item;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.neoforged.neoforge.energy.EnergyStorage;
|
||||
|
||||
final class PoweredEnergyHandler extends EnergyStorage {
|
||||
private final ItemStack stack;
|
||||
|
||||
PoweredEnergyHandler(ItemStack stack, int capacity, int maxTransfer, int energy) {
|
||||
super(capacity, maxTransfer, maxTransfer, energy);
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int receiveEnergy(int maxReceive, boolean simulate) {
|
||||
int received = super.receiveEnergy(maxReceive, simulate);
|
||||
if (!simulate && received > 0) {
|
||||
PoweredItemEnergy.setStoredEnergy(this.stack, this.energy);
|
||||
}
|
||||
return received;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extractEnergy(int maxExtract, boolean simulate) {
|
||||
int extracted = super.extractEnergy(maxExtract, simulate);
|
||||
if (!simulate && extracted > 0) {
|
||||
PoweredItemEnergy.setStoredEnergy(this.stack, this.energy);
|
||||
}
|
||||
return extracted;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.trunksbomb.batteries.v21_1.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.energy.IEnergyStorage;
|
||||
|
||||
public interface PoweredItem {
|
||||
default IEnergyStorage createEnergyHandler(ItemStack stack) {
|
||||
return PoweredItemEnergy.createEnergyHandler(stack, this.getMaxTransfer(stack));
|
||||
}
|
||||
|
||||
default int getMaxTransfer(ItemStack stack) {
|
||||
return com.trunksbomb.batteries.item.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());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
package com.trunksbomb.batteries.v21_1.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.energy.IEnergyStorage;
|
||||
|
||||
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 IEnergyStorage 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();
|
||||
int energy = tag.contains(ENERGY_KEY) ? tag.getInt(ENERGY_KEY) : 0;
|
||||
return Math.max(0, Math.min(energy, getEnergyCapacity(stack)));
|
||||
}
|
||||
|
||||
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 = tag.contains(CAPACITY_KEY) ? Math.max(0, tag.getInt(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);
|
||||
int existing = tag.contains(ENERGY_KEY) ? tag.getInt(ENERGY_KEY) : 0;
|
||||
tag.putInt(ENERGY_KEY, Math.max(0, Math.min(existing, 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);
|
||||
return capacity <= 0 ? 0 : 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.location().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.location().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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
package com.trunksbomb.batteries.v21_1.menu;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesNeoForge121;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryItem;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.ClickType;
|
||||
import net.minecraft.world.inventory.ContainerData;
|
||||
import net.minecraft.world.inventory.SimpleContainerData;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.component.CustomData;
|
||||
|
||||
public class BatteriesMenu extends AbstractContainerMenu {
|
||||
public static final int BATTERY_BUTTON_COUNT = 7;
|
||||
public static final int FILTER_SLOT_COUNT = 9;
|
||||
|
||||
private static final String BATTERY_WHITELIST_KEY = "whitelist";
|
||||
private static final String FILTER_SLOT_KEY_PREFIX = "filter_slot_";
|
||||
private static final String[] BATTERY_BUTTON_KEYS = new String[] {
|
||||
"whitelist",
|
||||
"blacklist",
|
||||
"charge_hotbar",
|
||||
"charge_inventory",
|
||||
"charge_armor",
|
||||
"charge_fairly",
|
||||
"charge_machine"
|
||||
};
|
||||
|
||||
private final InteractionHand hand;
|
||||
private final ContainerData toggleData;
|
||||
private final SimpleContainer filterSlots;
|
||||
private final Inventory playerInventory;
|
||||
|
||||
public BatteriesMenu(int containerId, Inventory inventory, RegistryFriendlyByteBuf buffer) {
|
||||
this(containerId, inventory, readHand(buffer), new SimpleContainerData(BATTERY_BUTTON_COUNT));
|
||||
}
|
||||
|
||||
private BatteriesMenu(int containerId, Inventory inventory, InteractionHand hand, ContainerData toggleData) {
|
||||
super(BatteriesNeoForge121.BATTERIES_MENU.get(), containerId);
|
||||
this.hand = hand;
|
||||
this.toggleData = toggleData;
|
||||
this.playerInventory = inventory;
|
||||
this.filterSlots = new SimpleContainer(FILTER_SLOT_COUNT);
|
||||
this.addDataSlots(toggleData);
|
||||
addSlots(inventory);
|
||||
}
|
||||
|
||||
public static BatteriesMenu forBattery(int containerId, Inventory inventory, InteractionHand hand) {
|
||||
SimpleContainerData data = new SimpleContainerData(BATTERY_BUTTON_COUNT);
|
||||
ItemStack stack = inventory.player.getItemInHand(hand);
|
||||
for (int i = 0; i < BATTERY_BUTTON_COUNT; i++) {
|
||||
data.set(i, getBatteryToggle(stack, resolveStateIndex(i)) ? 1 : 0);
|
||||
}
|
||||
BatteriesMenu menu = new BatteriesMenu(containerId, inventory, hand, data);
|
||||
menu.loadFilterSlots(stack);
|
||||
return menu;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clickMenuButton(Player player, int buttonId) {
|
||||
if (buttonId < 0 || buttonId >= this.toggleData.getCount()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int stateIndex = resolveStateIndex(buttonId);
|
||||
int newValue = this.toggleData.get(stateIndex) == 0 ? 1 : 0;
|
||||
this.toggleData.set(stateIndex, newValue);
|
||||
|
||||
if (!player.level().isClientSide() && this.hand != null) {
|
||||
setBatteryToggle(player.getItemInHand(this.hand), stateIndex, newValue == 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clicked(int slotId, int button, ClickType clickType, Player player) {
|
||||
if (slotId >= 0 && slotId < FILTER_SLOT_COUNT) {
|
||||
Slot slot = this.slots.get(slotId);
|
||||
ItemStack carried = this.getCarried();
|
||||
if (!carried.isEmpty() && slot.mayPlace(carried)) {
|
||||
ItemStack ghostStack = carried.copy();
|
||||
ghostStack.setCount(1);
|
||||
slot.set(ghostStack);
|
||||
} else {
|
||||
slot.set(ItemStack.EMPTY);
|
||||
}
|
||||
if (!player.level().isClientSide() && this.hand != null) {
|
||||
saveFilterSlots(player.getItemInHand(this.hand));
|
||||
}
|
||||
this.broadcastChanges();
|
||||
return;
|
||||
}
|
||||
|
||||
super.clicked(slotId, button, clickType, player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack quickMoveStack(Player player, int index) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(Player player) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int buttonCount() {
|
||||
return BATTERY_BUTTON_COUNT;
|
||||
}
|
||||
|
||||
public boolean isButtonEnabled(int index) {
|
||||
return this.toggleData.get(resolveStateIndex(index)) == 1;
|
||||
}
|
||||
|
||||
public void toggleClientPreview(int index) {
|
||||
if (index < 0 || index >= this.buttonCount()) {
|
||||
return;
|
||||
}
|
||||
int stateIndex = resolveStateIndex(index);
|
||||
this.toggleData.set(stateIndex, this.toggleData.get(stateIndex) == 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
public static String buttonTranslationKey(int index) {
|
||||
return "batteries.gui.button." + BATTERY_BUTTON_KEYS[index];
|
||||
}
|
||||
|
||||
public boolean isFilterSlotEmpty(int index) {
|
||||
return this.filterSlots.getItem(index).isEmpty();
|
||||
}
|
||||
|
||||
public ItemStack playerInventoryItem(int index) {
|
||||
return this.playerInventory.getItem(index);
|
||||
}
|
||||
|
||||
public ItemStack batteryStack() {
|
||||
return this.hand == null ? ItemStack.EMPTY : this.playerInventory.player.getItemInHand(this.hand);
|
||||
}
|
||||
|
||||
public static void writeBatteryMenu(RegistryFriendlyByteBuf buffer, InteractionHand hand) {
|
||||
buffer.writeEnum(hand);
|
||||
}
|
||||
|
||||
private static InteractionHand readHand(RegistryFriendlyByteBuf buffer) {
|
||||
return buffer.readEnum(InteractionHand.class);
|
||||
}
|
||||
|
||||
private static boolean getBatteryToggle(ItemStack stack, int index) {
|
||||
CustomData customData = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY);
|
||||
return customData.copyTag().getBoolean(stateKey(index));
|
||||
}
|
||||
|
||||
private static void setBatteryToggle(ItemStack stack, int index, boolean enabled) {
|
||||
CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> tag.putBoolean(stateKey(index), enabled));
|
||||
}
|
||||
|
||||
private void addSlots(Inventory inventory) {
|
||||
for (int i = 0; i < FILTER_SLOT_COUNT; i++) {
|
||||
this.addSlot(new BatteryFilterSlot(this.filterSlots, i, 32 + i * 18, 19));
|
||||
}
|
||||
|
||||
for (int row = 0; row < 3; row++) {
|
||||
for (int col = 0; col < 9; col++) {
|
||||
this.addSlot(new Slot(inventory, col + row * 9 + 9, 32 + col * 18, 82 + row * 18));
|
||||
}
|
||||
}
|
||||
|
||||
for (int col = 0; col < 9; col++) {
|
||||
this.addSlot(new Slot(inventory, col, 32 + col * 18, 140));
|
||||
}
|
||||
|
||||
for (int slotIndex = 39; slotIndex >= 36; slotIndex--) {
|
||||
int armorOffset = -slotIndex + 39;
|
||||
this.addSlot(new Slot(inventory, slotIndex, 7, 19 + armorOffset * 18));
|
||||
}
|
||||
|
||||
this.addSlot(new Slot(inventory, 40, 7, 91));
|
||||
}
|
||||
|
||||
private void loadFilterSlots(ItemStack stack) {
|
||||
CompoundTag tag = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag();
|
||||
for (int i = 0; i < FILTER_SLOT_COUNT; i++) {
|
||||
this.filterSlots.setItem(i, decodeFilterStack(tag.getString(filterSlotKey(i))));
|
||||
}
|
||||
}
|
||||
|
||||
private void saveFilterSlots(ItemStack stack) {
|
||||
CustomData.update(DataComponents.CUSTOM_DATA, stack, tag -> {
|
||||
for (int i = 0; i < FILTER_SLOT_COUNT; i++) {
|
||||
ItemStack filterStack = this.filterSlots.getItem(i);
|
||||
if (filterStack.isEmpty()) {
|
||||
tag.remove(filterSlotKey(i));
|
||||
} else {
|
||||
tag.putString(filterSlotKey(i), BuiltInRegistries.ITEM.getKey(filterStack.getItem()).toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static ItemStack decodeFilterStack(String itemId) {
|
||||
if (itemId == null || itemId.isBlank()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
ItemStack stack = new ItemStack(BuiltInRegistries.ITEM.get(ResourceLocation.parse(itemId)));
|
||||
return stack.isEmpty() ? ItemStack.EMPTY : stack;
|
||||
}
|
||||
|
||||
private static int resolveStateIndex(int buttonId) {
|
||||
return buttonId == 1 ? 0 : buttonId;
|
||||
}
|
||||
|
||||
private static String stateKey(int index) {
|
||||
return switch (index) {
|
||||
case 0 -> BATTERY_WHITELIST_KEY;
|
||||
case 2 -> "charge_hotbar";
|
||||
case 3 -> "charge_inventory";
|
||||
case 4 -> "charge_armor";
|
||||
case 5 -> "charge_fairly";
|
||||
case 6 -> "charge_machine";
|
||||
default -> throw new IllegalArgumentException("Unexpected battery state index: " + index);
|
||||
};
|
||||
}
|
||||
|
||||
private static String filterSlotKey(int index) {
|
||||
return FILTER_SLOT_KEY_PREFIX + index;
|
||||
}
|
||||
|
||||
private static class BatteryFilterSlot extends Slot {
|
||||
public BatteryFilterSlot(SimpleContainer container, int slot, int x, int y) {
|
||||
super(container, slot, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayPlace(ItemStack stack) {
|
||||
return !(stack.getItem() instanceof BatteryItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxStackSize() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package com.trunksbomb.batteries.v21_1.menu;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesNeoForge121;
|
||||
import com.trunksbomb.batteries.shared.BatteryBlockData;
|
||||
import com.trunksbomb.batteries.v21_1.block.entity.BatteryBlockEntity;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.ContainerData;
|
||||
import net.minecraft.world.inventory.ContainerLevelAccess;
|
||||
import net.minecraft.world.inventory.SimpleContainerData;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class BatteryBlockMenu extends AbstractContainerMenu {
|
||||
public static final int SIDE_BUTTON_COUNT = 6;
|
||||
private static final int ENERGY_INDEX = 6;
|
||||
private static final int CAPACITY_INDEX = 7;
|
||||
|
||||
private final ContainerLevelAccess access;
|
||||
private final ContainerData data;
|
||||
|
||||
public BatteryBlockMenu(int containerId, Inventory inventory, RegistryFriendlyByteBuf buffer) {
|
||||
this(containerId, inventory, buffer.readBlockPos(), createPlaceholderData());
|
||||
}
|
||||
|
||||
private BatteryBlockMenu(int containerId, Inventory inventory, BlockPos blockPos, ContainerData data) {
|
||||
super(BatteriesNeoForge121.BATTERY_BLOCK_MENU.get(), containerId);
|
||||
this.access = ContainerLevelAccess.create(inventory.player.level(), blockPos);
|
||||
this.data = data;
|
||||
this.addDataSlots(data);
|
||||
this.addPlayerSlots(inventory);
|
||||
}
|
||||
|
||||
public static BatteryBlockMenu forBlock(int containerId, Inventory inventory, BatteryBlockEntity blockEntity) {
|
||||
return new BatteryBlockMenu(containerId, inventory, blockEntity.getBlockPos(), new ContainerData() {
|
||||
@Override
|
||||
public int get(int index) {
|
||||
if (index >= 0 && index < SIDE_BUTTON_COUNT) {
|
||||
return blockEntity.getSideMode(BatteryBlockEntity.directionForIndex(index)).ordinal();
|
||||
}
|
||||
if (index == ENERGY_INDEX) {
|
||||
return blockEntity.getStoredEnergy();
|
||||
}
|
||||
if (index == CAPACITY_INDEX) {
|
||||
return blockEntity.getEnergyCapacity();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, int value) {
|
||||
if (index >= 0 && index < SIDE_BUTTON_COUNT) {
|
||||
BatteryBlockData.SideMode[] modes = BatteryBlockData.SideMode.values();
|
||||
blockEntity.setSideMode(BatteryBlockEntity.directionForIndex(index), modes[Math.max(0, Math.min(modes.length - 1, value))]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 8;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clickMenuButton(Player player, int buttonId) {
|
||||
if (buttonId < 0 || buttonId >= SIDE_BUTTON_COUNT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.data.set(buttonId, (this.data.get(buttonId) + 1) % BatteryBlockData.SideMode.values().length);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack quickMoveStack(Player player, int index) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(Player player) {
|
||||
return stillValid(this.access, player, BatteriesNeoForge121.BATTERY_BLOCK.get());
|
||||
}
|
||||
|
||||
public BatteryBlockData.SideMode sideMode(int index) {
|
||||
return BatteryBlockData.SideMode.values()[this.data.get(index)];
|
||||
}
|
||||
|
||||
public int storedEnergy() {
|
||||
return this.data.get(ENERGY_INDEX);
|
||||
}
|
||||
|
||||
public int energyCapacity() {
|
||||
return this.data.get(CAPACITY_INDEX);
|
||||
}
|
||||
|
||||
public void cycleClientPreview(int index) {
|
||||
if (index >= 0 && index < SIDE_BUTTON_COUNT) {
|
||||
this.data.set(index, (this.data.get(index) + 1) % BatteryBlockData.SideMode.values().length);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeBlockPos(RegistryFriendlyByteBuf buffer, BlockPos blockPos) {
|
||||
buffer.writeBlockPos(blockPos);
|
||||
}
|
||||
|
||||
private void addPlayerSlots(Inventory inventory) {
|
||||
for (int row = 0; row < 3; row++) {
|
||||
for (int col = 0; col < 9; col++) {
|
||||
this.addSlot(new Slot(inventory, col + row * 9 + 9, 8 + col * 18, 82 + row * 18));
|
||||
}
|
||||
}
|
||||
|
||||
for (int col = 0; col < 9; col++) {
|
||||
this.addSlot(new Slot(inventory, col, 8 + col * 18, 140));
|
||||
}
|
||||
}
|
||||
|
||||
private static ContainerData createPlaceholderData() {
|
||||
return new SimpleContainerData(8);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package com.trunksbomb.batteries.v21_1.menu;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesNeoForge121;
|
||||
import com.trunksbomb.batteries.v21_1.block.entity.CoalGeneratorBlockEntity;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.ContainerData;
|
||||
import net.minecraft.world.inventory.ContainerLevelAccess;
|
||||
import net.minecraft.world.inventory.SimpleContainerData;
|
||||
import net.minecraft.world.inventory.Slot;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class CoalGeneratorMenu extends AbstractContainerMenu {
|
||||
private static final int ENERGY_INDEX = 0;
|
||||
private static final int CAPACITY_INDEX = 1;
|
||||
private static final int BURN_TIME_INDEX = 2;
|
||||
private static final int MAX_BURN_TIME_INDEX = 3;
|
||||
|
||||
private final ContainerLevelAccess access;
|
||||
private final ContainerData data;
|
||||
|
||||
public CoalGeneratorMenu(int containerId, Inventory inventory, RegistryFriendlyByteBuf buffer) {
|
||||
this(containerId, inventory, buffer.readBlockPos(), createPlaceholderData(), new SimpleContainer(1));
|
||||
}
|
||||
|
||||
private CoalGeneratorMenu(int containerId, Inventory inventory, BlockPos blockPos, ContainerData data, Container fuelContainer) {
|
||||
super(BatteriesNeoForge121.COAL_GENERATOR_MENU.get(), containerId);
|
||||
this.access = ContainerLevelAccess.create(inventory.player.level(), blockPos);
|
||||
this.data = data;
|
||||
this.addDataSlots(data);
|
||||
this.addSlot(new FuelSlot(fuelContainer, 0, 80, 42));
|
||||
this.addPlayerSlots(inventory);
|
||||
}
|
||||
|
||||
public static CoalGeneratorMenu forBlock(int containerId, Inventory inventory, CoalGeneratorBlockEntity blockEntity) {
|
||||
ContainerData data = new ContainerData() {
|
||||
@Override
|
||||
public int get(int index) {
|
||||
return switch (index) {
|
||||
case ENERGY_INDEX -> blockEntity.getStoredEnergy();
|
||||
case CAPACITY_INDEX -> blockEntity.getEnergyCapacity();
|
||||
case BURN_TIME_INDEX -> blockEntity.getBurnTimeRemaining();
|
||||
case MAX_BURN_TIME_INDEX -> blockEntity.getMaxBurnTime();
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, int value) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return 4;
|
||||
}
|
||||
};
|
||||
return new CoalGeneratorMenu(containerId, inventory, blockEntity.getBlockPos(), data, blockEntity.fuelSlot());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack quickMoveStack(Player player, int index) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stillValid(Player player) {
|
||||
return stillValid(this.access, player, BatteriesNeoForge121.COAL_GENERATOR.get());
|
||||
}
|
||||
|
||||
public int storedEnergy() {
|
||||
return this.data.get(ENERGY_INDEX);
|
||||
}
|
||||
|
||||
public int energyCapacity() {
|
||||
return this.data.get(CAPACITY_INDEX);
|
||||
}
|
||||
|
||||
public int burnTimeRemaining() {
|
||||
return this.data.get(BURN_TIME_INDEX);
|
||||
}
|
||||
|
||||
public int maxBurnTime() {
|
||||
return this.data.get(MAX_BURN_TIME_INDEX);
|
||||
}
|
||||
|
||||
public static void writeBlockPos(RegistryFriendlyByteBuf buffer, BlockPos blockPos) {
|
||||
buffer.writeBlockPos(blockPos);
|
||||
}
|
||||
|
||||
private void addPlayerSlots(Inventory inventory) {
|
||||
for (int row = 0; row < 3; row++) {
|
||||
for (int col = 0; col < 9; col++) {
|
||||
this.addSlot(new Slot(inventory, col + row * 9 + 9, 8 + col * 18, 82 + row * 18));
|
||||
}
|
||||
}
|
||||
for (int col = 0; col < 9; col++) {
|
||||
this.addSlot(new Slot(inventory, col, 8 + col * 18, 140));
|
||||
}
|
||||
}
|
||||
|
||||
private static ContainerData createPlaceholderData() {
|
||||
return new SimpleContainerData(4);
|
||||
}
|
||||
|
||||
private final class FuelSlot extends Slot {
|
||||
private FuelSlot(Container container, int slot, int x, int y) {
|
||||
super(container, slot, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mayPlace(ItemStack stack) {
|
||||
return CoalGeneratorMenu.this.access.evaluate((level, pos) -> CoalGeneratorBlockEntity.isFuel(level, stack), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.trunksbomb.batteries.v21_1.recipe;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesNeoForge121;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryBlockItem;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryItem;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
||||
import net.minecraft.world.item.crafting.CraftingInput;
|
||||
import net.minecraft.world.item.crafting.CustomRecipe;
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class BatteryBlockUpgradeRecipe extends CustomRecipe {
|
||||
public BatteryBlockUpgradeRecipe(CraftingBookCategory category) {
|
||||
super(category);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(CraftingInput input, @NonNull Level level) {
|
||||
return this.findMatch(input) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ItemStack assemble(CraftingInput input, HolderLookup.@NonNull Provider registries) {
|
||||
Match match = this.findMatch(input);
|
||||
if (match == null) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
ItemStack result = new ItemStack(BatteriesNeoForge121.BATTERY_BLOCK_ITEM.get());
|
||||
int newCapacity = clampToInt((long) match.baseCapacity() + match.addedCapacity());
|
||||
int newEnergy = clampToInt((long) match.baseEnergy() + match.addedEnergy());
|
||||
BatteryBlockItem.setEnergyCapacity(result, newCapacity);
|
||||
BatteryBlockItem.setStoredEnergy(result, Math.min(newCapacity, newEnergy));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull RecipeSerializer<? extends CustomRecipe> getSerializer() {
|
||||
return BatteriesNeoForge121.BATTERY_BLOCK_UPGRADE_RECIPE.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCraftInDimensions(int width, int height) {
|
||||
return width * height >= 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ItemStack getResultItem(HolderLookup.@NonNull Provider registries) {
|
||||
ItemStack result = new ItemStack(BatteriesNeoForge121.BATTERY_BLOCK_ITEM.get());
|
||||
BatteryBlockItem.initializeDefaults(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Match findMatch(CraftingInput input) {
|
||||
ItemStack baseStack = ItemStack.EMPTY;
|
||||
long addedCapacity = 0L;
|
||||
long addedEnergy = 0L;
|
||||
|
||||
for (ItemStack stack : input.items()) {
|
||||
if (stack.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stack.getItem() instanceof BatteryBlockItem) {
|
||||
if (baseStack.isEmpty()) {
|
||||
baseStack = stack;
|
||||
} else {
|
||||
addedCapacity += BatteryBlockItem.getEnergyCapacity(stack);
|
||||
addedEnergy += BatteryBlockItem.getStoredEnergy(stack);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stack.getItem() instanceof BatteryItem) {
|
||||
addedCapacity += BatteryItem.getEnergyCapacity(stack);
|
||||
addedEnergy += BatteryItem.getStoredEnergy(stack);
|
||||
continue;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (baseStack.isEmpty() || addedCapacity <= 0L) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Match(
|
||||
BatteryBlockItem.getEnergyCapacity(baseStack),
|
||||
BatteryBlockItem.getStoredEnergy(baseStack),
|
||||
clampToInt(addedCapacity),
|
||||
clampToInt(addedEnergy)
|
||||
);
|
||||
}
|
||||
|
||||
private static int clampToInt(long value) {
|
||||
return (int) Math.max(0L, Math.min(Integer.MAX_VALUE, value));
|
||||
}
|
||||
|
||||
private record Match(int baseCapacity, int baseEnergy, int addedCapacity, int addedEnergy) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.trunksbomb.batteries.v21_1.recipe;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesNeoForge121;
|
||||
import com.trunksbomb.batteries.item.BatteryItemData;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryItem;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
||||
import net.minecraft.world.item.crafting.CraftingInput;
|
||||
import net.minecraft.world.item.crafting.CustomRecipe;
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class BatteryTierUpgradeRecipe extends CustomRecipe {
|
||||
public BatteryTierUpgradeRecipe(CraftingBookCategory category) {
|
||||
super(category);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(CraftingInput input, @NonNull Level level) {
|
||||
return this.findMatch(input) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ItemStack assemble(CraftingInput input, HolderLookup.@NonNull Provider registries) {
|
||||
Match match = this.findMatch(input);
|
||||
if (match == null) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
ItemStack result = new ItemStack(match.resultItem());
|
||||
BatteryItem.createEnergyHandler(result);
|
||||
BatteryItemData.setStoredEnergy(result, Math.min(BatteryItem.getStoredEnergy(match.baseStack()), BatteryItem.getEnergyCapacity(result)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull RecipeSerializer<? extends CustomRecipe> getSerializer() {
|
||||
return BatteriesNeoForge121.BATTERY_TIER_UPGRADE_RECIPE.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCraftInDimensions(int width, int height) {
|
||||
return width >= 3 && height >= 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ItemStack getResultItem(HolderLookup.@NonNull Provider registries) {
|
||||
return new ItemStack(BatteriesNeoForge121.BATTERY1.get());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Match findMatch(CraftingInput input) {
|
||||
if (input.width() != 3 || input.height() != 3) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (matchesPattern(input, Items.REDSTONE, Items.GOLD_BLOCK, BatteriesNeoForge121.BATTERY.get(), Items.REDSTONE_BLOCK)) {
|
||||
return new Match(input.getItem(4), BatteriesNeoForge121.BATTERY1.get());
|
||||
}
|
||||
if (matchesPattern(input, Items.REDSTONE, Items.DIAMOND, BatteriesNeoForge121.BATTERY1.get(), Items.REDSTONE_BLOCK)) {
|
||||
return new Match(input.getItem(4), BatteriesNeoForge121.BATTERY2.get());
|
||||
}
|
||||
if (matchesPattern(input, Items.REDSTONE, Items.DIAMOND_BLOCK, BatteriesNeoForge121.BATTERY2.get(), Items.REDSTONE_BLOCK)) {
|
||||
return new Match(input.getItem(4), BatteriesNeoForge121.BATTERY3.get());
|
||||
}
|
||||
if (matchesPattern(input, Items.END_STONE, Items.DIAMOND_BLOCK, BatteriesNeoForge121.BATTERY3.get(), Items.ENDER_PEARL)) {
|
||||
return new Match(input.getItem(4), BatteriesNeoForge121.BATTERY_ENDER.get());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean matchesPattern(CraftingInput input, Item cornerItem, Item topBottomItem, Item centerItem, Item middleSideItem) {
|
||||
return input.getItem(0).is(cornerItem)
|
||||
&& input.getItem(1).is(topBottomItem)
|
||||
&& input.getItem(2).is(cornerItem)
|
||||
&& input.getItem(3).is(middleSideItem)
|
||||
&& input.getItem(4).is(centerItem)
|
||||
&& input.getItem(5).is(middleSideItem)
|
||||
&& input.getItem(6).is(cornerItem)
|
||||
&& input.getItem(7).is(topBottomItem)
|
||||
&& input.getItem(8).is(cornerItem);
|
||||
}
|
||||
|
||||
private record Match(ItemStack baseStack, Item resultItem) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package com.trunksbomb.batteries.v21_1.recipe;
|
||||
|
||||
import com.trunksbomb.batteries.BatteriesConfig;
|
||||
import com.trunksbomb.batteries.BatteriesNeoForge121;
|
||||
import com.trunksbomb.batteries.v21_1.item.BatteryItem;
|
||||
import com.trunksbomb.batteries.v21_1.item.PoweredItem;
|
||||
import com.trunksbomb.batteries.v21_1.item.PoweredItemEnergy;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.crafting.CraftingBookCategory;
|
||||
import net.minecraft.world.item.crafting.CraftingInput;
|
||||
import net.minecraft.world.item.crafting.CustomRecipe;
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class PoweredGearUpgradeRecipe extends CustomRecipe {
|
||||
public PoweredGearUpgradeRecipe(CraftingBookCategory category) {
|
||||
super(category);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(CraftingInput input, @NonNull Level level) {
|
||||
return this.findMatch(input) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ItemStack assemble(CraftingInput input, HolderLookup.@NonNull Provider registries) {
|
||||
Match match = this.findMatch(input);
|
||||
if (match == null) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
ItemStack result = new ItemStack(match.resultItem());
|
||||
int baseCapacity = match.basePowered() ? PoweredItemEnergy.getEnergyCapacity(match.baseStack()) : 0;
|
||||
int baseEnergy = match.basePowered() ? PoweredItemEnergy.getStoredEnergy(match.baseStack()) : 0;
|
||||
int newCapacity = PoweredItemEnergy.clampToInt((long) baseCapacity + match.addedCapacity());
|
||||
int newEnergy = PoweredItemEnergy.clampToInt((long) baseEnergy + match.addedEnergy());
|
||||
PoweredItemEnergy.setEnergyCapacity(result, newCapacity);
|
||||
PoweredItemEnergy.setStoredEnergy(result, Math.min(newCapacity, newEnergy));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull RecipeSerializer<? extends CustomRecipe> getSerializer() {
|
||||
return BatteriesNeoForge121.POWERED_GEAR_UPGRADE_RECIPE.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCraftInDimensions(int width, int height) {
|
||||
return width * height >= 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull ItemStack getResultItem(HolderLookup.@NonNull Provider registries) {
|
||||
return new ItemStack(BatteriesNeoForge121.BATTERY_PICKAXE.get());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Match findMatch(CraftingInput input) {
|
||||
ItemStack baseStack = ItemStack.EMPTY;
|
||||
Item resultItem = null;
|
||||
boolean basePowered = false;
|
||||
long addedCapacity = 0L;
|
||||
long addedEnergy = 0L;
|
||||
int batteries = 0;
|
||||
|
||||
for (ItemStack stack : input.items()) {
|
||||
if (stack.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stack.getItem() instanceof BatteryItem) {
|
||||
batteries++;
|
||||
addedCapacity += BatteryItem.getEnergyCapacity(stack);
|
||||
addedEnergy += BatteryItem.getStoredEnergy(stack);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!baseStack.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
resultItem = this.toPoweredResult(stack);
|
||||
if (resultItem == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
baseStack = stack;
|
||||
basePowered = stack.getItem() instanceof PoweredItem;
|
||||
}
|
||||
|
||||
if (baseStack.isEmpty() || resultItem == null || batteries == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Match(baseStack, resultItem, basePowered, PoweredItemEnergy.clampToInt(addedCapacity), PoweredItemEnergy.clampToInt(addedEnergy));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Item toPoweredResult(ItemStack stack) {
|
||||
Item item = stack.getItem();
|
||||
if (BatteriesConfig.poweredToolsEnabled() && item == Items.DIAMOND_PICKAXE) {
|
||||
return BatteriesNeoForge121.BATTERY_PICKAXE.get();
|
||||
}
|
||||
if (BatteriesConfig.poweredToolsEnabled() && item == Items.DIAMOND_AXE) {
|
||||
return BatteriesNeoForge121.BATTERY_AXE.get();
|
||||
}
|
||||
if (BatteriesConfig.poweredToolsEnabled() && item == Items.DIAMOND_SHOVEL) {
|
||||
return BatteriesNeoForge121.BATTERY_SHOVEL.get();
|
||||
}
|
||||
if (BatteriesConfig.poweredToolsEnabled() && item == Items.DIAMOND_HOE) {
|
||||
return BatteriesNeoForge121.BATTERY_HOE.get();
|
||||
}
|
||||
if (BatteriesConfig.poweredWeaponsEnabled() && item == Items.DIAMOND_SWORD) {
|
||||
return BatteriesNeoForge121.BATTERY_SWORD.get();
|
||||
}
|
||||
if (BatteriesConfig.poweredArmorEnabled() && item == Items.DIAMOND_HELMET) {
|
||||
return BatteriesNeoForge121.BATTERY_HELMET.get();
|
||||
}
|
||||
if (BatteriesConfig.poweredArmorEnabled() && item == Items.DIAMOND_CHESTPLATE) {
|
||||
return BatteriesNeoForge121.BATTERY_CHESTPLATE.get();
|
||||
}
|
||||
if (BatteriesConfig.poweredArmorEnabled() && item == Items.DIAMOND_LEGGINGS) {
|
||||
return BatteriesNeoForge121.BATTERY_LEGGINGS.get();
|
||||
}
|
||||
if (BatteriesConfig.poweredArmorEnabled() && item == Items.DIAMOND_BOOTS) {
|
||||
return BatteriesNeoForge121.BATTERY_BOOTS.get();
|
||||
}
|
||||
if (BatteriesConfig.poweredWeaponsEnabled() && item == Items.SHIELD) {
|
||||
return BatteriesNeoForge121.BATTERY_SHIELD.get();
|
||||
}
|
||||
if (BatteriesConfig.poweredWeaponsEnabled() && item == Items.BOW) {
|
||||
return BatteriesNeoForge121.BATTERY_BOW.get();
|
||||
}
|
||||
if (BatteriesConfig.poweredToolsEnabled() && (item == BatteriesNeoForge121.BATTERY_PICKAXE.get()
|
||||
|| item == BatteriesNeoForge121.BATTERY_AXE.get()
|
||||
|| item == BatteriesNeoForge121.BATTERY_SHOVEL.get()
|
||||
|| item == BatteriesNeoForge121.BATTERY_HOE.get())) {
|
||||
return item;
|
||||
}
|
||||
if (BatteriesConfig.poweredWeaponsEnabled() && (item == BatteriesNeoForge121.BATTERY_SWORD.get()
|
||||
|| item == BatteriesNeoForge121.BATTERY_SHIELD.get()
|
||||
|| item == BatteriesNeoForge121.BATTERY_BOW.get())) {
|
||||
return item;
|
||||
}
|
||||
if (BatteriesConfig.poweredArmorEnabled() && (item == BatteriesNeoForge121.BATTERY_HELMET.get()
|
||||
|| item == BatteriesNeoForge121.BATTERY_CHESTPLATE.get()
|
||||
|| item == BatteriesNeoForge121.BATTERY_LEGGINGS.get()
|
||||
|| item == BatteriesNeoForge121.BATTERY_BOOTS.get())) {
|
||||
return item;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private record Match(ItemStack baseStack, Item resultItem, boolean basePowered, int addedCapacity, int addedEnergy) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package net.neoforged.neoforge.transfer;
|
||||
|
||||
import net.neoforged.neoforge.transfer.transaction.TransactionContext;
|
||||
|
||||
public interface ResourceHandler<T> {
|
||||
int size();
|
||||
|
||||
T getResource(int index);
|
||||
|
||||
long getAmountAsLong(int index);
|
||||
|
||||
long getCapacityAsLong(int index, T resource);
|
||||
|
||||
boolean isValid(int index, T resource);
|
||||
|
||||
int insert(int index, T resource, int amount, TransactionContext transaction);
|
||||
|
||||
default int insert(T resource, int amount, TransactionContext transaction) {
|
||||
TransferPreconditions.checkNonEmptyNonNegative((net.neoforged.neoforge.transfer.item.ItemResource) resource, amount);
|
||||
int inserted = 0;
|
||||
for (int index = 0; index < size(); index++) {
|
||||
inserted += insert(index, resource, amount - inserted, transaction);
|
||||
if (inserted >= amount) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return inserted;
|
||||
}
|
||||
|
||||
int extract(int index, T resource, int amount, TransactionContext transaction);
|
||||
|
||||
default int extract(T resource, int amount, TransactionContext transaction) {
|
||||
TransferPreconditions.checkNonEmptyNonNegative((net.neoforged.neoforge.transfer.item.ItemResource) resource, amount);
|
||||
int extracted = 0;
|
||||
for (int index = 0; index < size(); index++) {
|
||||
extracted += extract(index, resource, amount - extracted, transaction);
|
||||
if (extracted >= amount) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return extracted;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T> Class<ResourceHandler<T>> asClass() {
|
||||
return (Class<ResourceHandler<T>>) (Object) ResourceHandler.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package net.neoforged.neoforge.transfer;
|
||||
|
||||
import net.neoforged.neoforge.transfer.item.ItemResource;
|
||||
|
||||
public final class TransferPreconditions {
|
||||
private TransferPreconditions() {
|
||||
}
|
||||
|
||||
public static void checkNonNegative(int amount) {
|
||||
if (amount < 0) {
|
||||
throw new IllegalArgumentException("Amount must be non-negative");
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkNonEmpty(ItemResource resource) {
|
||||
if (resource == null || resource.isEmpty()) {
|
||||
throw new IllegalArgumentException("Resource must be non-empty");
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkNonEmptyNonNegative(ItemResource resource, int amount) {
|
||||
checkNonEmpty(resource);
|
||||
checkNonNegative(amount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package net.neoforged.neoforge.transfer.energy;
|
||||
|
||||
import net.neoforged.neoforge.transfer.transaction.TransactionContext;
|
||||
|
||||
public interface EnergyHandler {
|
||||
long getAmountAsLong();
|
||||
|
||||
int getEnergyStored();
|
||||
|
||||
int getMaxEnergyStored();
|
||||
|
||||
boolean canExtract();
|
||||
|
||||
boolean canInsert();
|
||||
|
||||
int insert(int maxAmount, TransactionContext transaction);
|
||||
|
||||
int extract(int maxAmount, TransactionContext transaction);
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package net.neoforged.neoforge.transfer.energy;
|
||||
|
||||
import net.neoforged.neoforge.transfer.transaction.Transaction;
|
||||
import net.neoforged.neoforge.transfer.transaction.TransactionContext;
|
||||
|
||||
public class SimpleEnergyHandler implements EnergyHandler {
|
||||
protected final int capacity;
|
||||
protected final int maxInsert;
|
||||
protected final int maxExtract;
|
||||
protected int energy;
|
||||
|
||||
public SimpleEnergyHandler(int capacity, int maxInsert, int maxExtract, int energy) {
|
||||
this.capacity = capacity;
|
||||
this.maxInsert = maxInsert;
|
||||
this.maxExtract = maxExtract;
|
||||
this.energy = Math.max(0, Math.min(capacity, energy));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAmountAsLong() {
|
||||
return this.energy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEnergyStored() {
|
||||
return this.energy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxEnergyStored() {
|
||||
return this.capacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExtract() {
|
||||
return this.maxExtract > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInsert() {
|
||||
return this.maxInsert > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insert(int maxAmount, TransactionContext transaction) {
|
||||
if (!canInsert() || maxAmount <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int inserted = Math.min(Math.min(this.capacity - this.energy, this.maxInsert), maxAmount);
|
||||
if (inserted <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int previous = this.energy;
|
||||
this.energy += inserted;
|
||||
if (transaction instanceof Transaction tx) {
|
||||
tx.addRollbackAction(() -> this.energy = previous);
|
||||
}
|
||||
onEnergyChanged(previous);
|
||||
return inserted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int extract(int maxAmount, TransactionContext transaction) {
|
||||
if (!canExtract() || maxAmount <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int extracted = Math.min(Math.min(this.energy, this.maxExtract), maxAmount);
|
||||
if (extracted <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int previous = this.energy;
|
||||
this.energy -= extracted;
|
||||
if (transaction instanceof Transaction tx) {
|
||||
tx.addRollbackAction(() -> this.energy = previous);
|
||||
}
|
||||
onEnergyChanged(previous);
|
||||
return extracted;
|
||||
}
|
||||
|
||||
public void set(int energy) {
|
||||
int previous = this.energy;
|
||||
this.energy = Math.max(0, Math.min(this.capacity, energy));
|
||||
if (previous != this.energy) {
|
||||
onEnergyChanged(previous);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onEnergyChanged(int previousAmount) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package net.neoforged.neoforge.transfer.item;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.neoforged.neoforge.transfer.TransferPreconditions;
|
||||
|
||||
public final class ItemResource {
|
||||
public static final ItemResource EMPTY = new ItemResource(ItemStack.EMPTY);
|
||||
|
||||
private final ItemStack stack;
|
||||
|
||||
private ItemResource(ItemStack stack) {
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
public static ItemResource of(ItemStack stack) {
|
||||
if (stack.isEmpty()) {
|
||||
return EMPTY;
|
||||
}
|
||||
return new ItemResource(stack.copyWithCount(1));
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.stack.isEmpty();
|
||||
}
|
||||
|
||||
public boolean matches(ItemStack other) {
|
||||
return ItemStack.isSameItemSameComponents(this.stack, other);
|
||||
}
|
||||
|
||||
public int getMaxStackSize() {
|
||||
return this.stack.getMaxStackSize();
|
||||
}
|
||||
|
||||
public ItemStack toStack(int count) {
|
||||
TransferPreconditions.checkNonNegative(count);
|
||||
return count <= 0 ? ItemStack.EMPTY : this.stack.copyWithCount(count);
|
||||
}
|
||||
|
||||
public ItemStack toStack() {
|
||||
return toStack(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package net.neoforged.neoforge.transfer.transaction;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class SnapshotJournal<T> {
|
||||
private final Map<Transaction, T> snapshots = new IdentityHashMap<>();
|
||||
|
||||
protected abstract T createSnapshot();
|
||||
|
||||
protected abstract void revertToSnapshot(T snapshot);
|
||||
|
||||
protected void onRootCommit(T snapshot) {
|
||||
}
|
||||
|
||||
public void updateSnapshots(TransactionContext transaction) {
|
||||
if (!(transaction instanceof Transaction tx) || this.snapshots.containsKey(tx)) {
|
||||
return;
|
||||
}
|
||||
|
||||
T snapshot = createSnapshot();
|
||||
this.snapshots.put(tx, snapshot);
|
||||
tx.addRollbackAction(() -> {
|
||||
T previous = this.snapshots.remove(tx);
|
||||
if (previous != null) {
|
||||
revertToSnapshot(previous);
|
||||
}
|
||||
});
|
||||
tx.addCommitAction(() -> {
|
||||
T previous = this.snapshots.remove(tx);
|
||||
if (previous != null) {
|
||||
onRootCommit(previous);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package net.neoforged.neoforge.transfer.transaction;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Transaction implements TransactionContext, AutoCloseable {
|
||||
private final List<Runnable> rollbackActions = new ArrayList<>();
|
||||
private final List<Runnable> commitActions = new ArrayList<>();
|
||||
private boolean committed;
|
||||
|
||||
public static Transaction openRoot() {
|
||||
return new Transaction();
|
||||
}
|
||||
|
||||
public static Transaction open(TransactionContext context) {
|
||||
return new Transaction();
|
||||
}
|
||||
|
||||
public void commit() {
|
||||
this.committed = true;
|
||||
for (Runnable action : this.commitActions) {
|
||||
action.run();
|
||||
}
|
||||
}
|
||||
|
||||
public void addRollbackAction(Runnable action) {
|
||||
this.rollbackActions.add(action);
|
||||
}
|
||||
|
||||
public void addCommitAction(Runnable action) {
|
||||
this.commitActions.add(action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (!this.committed) {
|
||||
for (int i = this.rollbackActions.size() - 1; i >= 0; i--) {
|
||||
this.rollbackActions.get(i).run();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package net.neoforged.neoforge.transfer.transaction;
|
||||
|
||||
public interface TransactionContext {
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "redstone",
|
||||
"pattern": [
|
||||
"rgr",
|
||||
"bib",
|
||||
"rgr"
|
||||
],
|
||||
"key": {
|
||||
"r": { "item": "minecraft:redstone" },
|
||||
"g": { "item": "minecraft:gold_ingot" },
|
||||
"i": { "item": "minecraft:iron_ingot" },
|
||||
"b": { "item": "minecraft:redstone_block" }
|
||||
},
|
||||
"result": {
|
||||
"id": "batteries:battery",
|
||||
"count": 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "batteries:battery_tier_upgrade",
|
||||
"category": "redstone"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "batteries:battery_tier_upgrade",
|
||||
"category": "redstone"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "batteries:battery_tier_upgrade",
|
||||
"category": "redstone"
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "redstone",
|
||||
"pattern": [
|
||||
"RGR",
|
||||
"LIL",
|
||||
"RGR"
|
||||
],
|
||||
"key": {
|
||||
"R": { "item": "minecraft:redstone_block" },
|
||||
"L": { "tag": "minecraft:logs" },
|
||||
"G": { "item": "minecraft:gold_ingot" },
|
||||
"I": { "item": "minecraft:iron_block" }
|
||||
},
|
||||
"result": {
|
||||
"id": "batteries:battery_block"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "batteries:battery_block_upgrade",
|
||||
"category": "redstone"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"type": "batteries:battery_tier_upgrade",
|
||||
"category": "redstone"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "redstone",
|
||||
"pattern": [
|
||||
"rgr",
|
||||
"bib",
|
||||
"rgr"
|
||||
],
|
||||
"key": {
|
||||
"r": { "item": "minecraft:white_concrete" },
|
||||
"g": { "item": "minecraft:gold_ingot" },
|
||||
"i": { "item": "minecraft:iron_ingot" },
|
||||
"b": { "item": "minecraft:redstone_block" }
|
||||
},
|
||||
"result": {
|
||||
"id": "batteries:charger",
|
||||
"count": 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "redstone",
|
||||
"pattern": [
|
||||
"RGR",
|
||||
"LFL",
|
||||
"RGR"
|
||||
],
|
||||
"key": {
|
||||
"R": { "item": "minecraft:redstone_block" },
|
||||
"G": { "item": "minecraft:gold_ingot" },
|
||||
"L": { "tag": "minecraft:logs" },
|
||||
"F": { "item": "minecraft:furnace" }
|
||||
},
|
||||
"result": {
|
||||
"id": "batteries:coal_generator"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "redstone",
|
||||
"pattern": [
|
||||
"ede",
|
||||
"ece",
|
||||
"ede"
|
||||
],
|
||||
"key": {
|
||||
"e": { "item": "minecraft:ender_pearl" },
|
||||
"d": { "item": "minecraft:diamond" },
|
||||
"c": { "item": "batteries:charger" }
|
||||
},
|
||||
"result": {
|
||||
"id": "batteries:ender_charger",
|
||||
"count": 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
# This is an example neoforge.mods.toml file. It contains the data relating to the loading mods.
|
||||
# There are several mandatory fields (#mandatory), and many more that are optional (#optional).
|
||||
# The overall format is standard TOML format, v0.5.0.
|
||||
# Note that there are a couple of TOML lists in this file.
|
||||
# Find more information on toml format here: https://github.com/toml-lang/toml
|
||||
|
||||
modLoader="javafml"
|
||||
loaderVersion="[1,)"
|
||||
license="${mod_license}"
|
||||
|
||||
[[mods]]
|
||||
modId="${mod_id}"
|
||||
version="${mod_version}"
|
||||
displayName="${mod_name}"
|
||||
authors="trunksbomb"
|
||||
description='''
|
||||
Adds portable batteries and chargers for NeoForge.
|
||||
'''
|
||||
|
||||
[[dependencies.${mod_id}]]
|
||||
modId="neoforge"
|
||||
type="required"
|
||||
versionRange="[${neo_version},)"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
||||
|
||||
[[dependencies.${mod_id}]]
|
||||
modId="minecraft"
|
||||
type="required"
|
||||
versionRange="${minecraft_version_range}"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
||||
Reference in New Issue
Block a user