From bafe6c23d9a23b71e813d8e526b2da64f49e0df6 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 13 Aug 2021 19:57:15 +0700 Subject: [PATCH] Matter decomposer! --- .../ru/dbotthepony/mc/otm/MatterRegistry.java | 13 +- .../java/ru/dbotthepony/mc/otm/Registry.java | 19 ++ .../mc/otm/block/BlockMatterDecomposer.java | 27 ++ .../entity/BlockEntityAndroidStation.java | 1 - .../block/entity/BlockEntityBatteryBank.java | 16 +- .../entity/BlockEntityMatterDecomposer.java | 243 ++++++++++++++++++ .../BlockEntityMatteryPoweredMachine.java | 17 +- .../mc/otm/capability/IMatterHandler.java | 30 +++ .../otm/capability/IMatteryEnergyStorage.java | 16 -- .../capability/MatterHandlerCapability.java | 164 ++++++++++++ .../mc/otm/capability/MatteryCapability.java | 7 +- .../dbotthepony/mc/otm/item/ItemBattery.java | 43 ++-- .../mc/otm/menu/AndroidStationMenu.java | 2 +- .../mc/otm/menu/FormattingHelper.java | 8 + .../mc/otm/menu/MatterDecomposerMenu.java | 105 ++++++++ .../mc/otm/menu/PoweredMatteryMenu.java | 9 +- .../mc/otm/menu/slot/BatterySlot.java | 15 +- .../mc/otm/menu/slot/MachineInputSlot.java | 19 ++ .../mc/otm/menu/slot/MachineOutputSlot.java | 25 ++ .../mc/otm/screen/BatteryBankScreen.java | 18 +- .../mc/otm/screen/MatterDecomposerScreen.java | 16 ++ .../mc/otm/screen/MatteryScreen.java | 242 ++++++++++++++--- .../mc/otm/screen/PoweredMachineScreen.java | 31 +-- .../overdrive_that_matters/lang/en_us.json | 4 +- .../textures/gui/android_station.png | Bin 10466 -> 9606 bytes .../textures/gui/android_station.xcf | Bin 24333 -> 21095 bytes .../textures/gui/battery_bank.png | Bin 1647 -> 0 bytes .../textures/gui/generic_machine.png | Bin 0 -> 9230 bytes .../{battery_bank.xcf => generic_machine.xcf} | Bin 27167 -> 19852 bytes .../textures/gui/mattery_machine_base.png | Bin 10115 -> 0 bytes .../textures/gui/widgets.png | Bin 0 -> 1812 bytes .../textures/gui/widgets.xcf | Bin 1050 -> 8003 bytes 32 files changed, 941 insertions(+), 149 deletions(-) create mode 100644 src/main/java/ru/dbotthepony/mc/otm/block/BlockMatterDecomposer.java create mode 100644 src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterDecomposer.java create mode 100644 src/main/java/ru/dbotthepony/mc/otm/capability/IMatterHandler.java create mode 100644 src/main/java/ru/dbotthepony/mc/otm/capability/MatterHandlerCapability.java create mode 100644 src/main/java/ru/dbotthepony/mc/otm/menu/MatterDecomposerMenu.java create mode 100644 src/main/java/ru/dbotthepony/mc/otm/menu/slot/MachineInputSlot.java create mode 100644 src/main/java/ru/dbotthepony/mc/otm/menu/slot/MachineOutputSlot.java create mode 100644 src/main/java/ru/dbotthepony/mc/otm/screen/MatterDecomposerScreen.java delete mode 100644 src/main/resources/assets/overdrive_that_matters/textures/gui/battery_bank.png create mode 100644 src/main/resources/assets/overdrive_that_matters/textures/gui/generic_machine.png rename src/main/resources/assets/overdrive_that_matters/textures/gui/{battery_bank.xcf => generic_machine.xcf} (69%) delete mode 100644 src/main/resources/assets/overdrive_that_matters/textures/gui/mattery_machine_base.png create mode 100644 src/main/resources/assets/overdrive_that_matters/textures/gui/widgets.png diff --git a/src/main/java/ru/dbotthepony/mc/otm/MatterRegistry.java b/src/main/java/ru/dbotthepony/mc/otm/MatterRegistry.java index a849ed3c2..d80966baa 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/MatterRegistry.java +++ b/src/main/java/ru/dbotthepony/mc/otm/MatterRegistry.java @@ -12,6 +12,7 @@ import net.minecraft.world.item.crafting.RecipeType; import net.minecraftforge.event.entity.player.ItemTooltipEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fmlserverevents.FMLServerStartedEvent; +import ru.dbotthepony.mc.otm.capability.MatteryCapability; import ru.dbotthepony.mc.otm.menu.FormattingHelper; import javax.annotation.Nullable; @@ -28,6 +29,15 @@ public class MatterRegistry { return ITEMS.getOrDefault(item, INITIAL_ITEMS.getOrDefault(item, BigDecimal.ZERO)); } + public static boolean hasMatterValue(Item item) { + return ITEMS.containsKey(item) || INITIAL_ITEMS.containsKey(item); + } + + public static boolean hasMatterValue(ItemStack item) { + return hasMatterValue(item.getItem()); + } + + public static BigDecimal getMatterValue(ItemStack stack) { Item item = stack.getItem(); @@ -280,7 +290,7 @@ public class MatterRegistry { private static final HashMap seen_items = new HashMap<>(); private static final HashMap seen_items_child = new HashMap<>(); - public static final MathContext ROUND_RULES = new MathContext(32, RoundingMode.DOWN); + public static final MathContext ROUND_RULES = MatteryCapability.ROUND_RULES; private static boolean solve_occured = false; private static Set defered_items = new HashSet<>(); @@ -468,6 +478,7 @@ public class MatterRegistry { // clean up garbage usages.clear(); results.clear(); + defered_items.clear(); ArrayList> required_resolve = new ArrayList<>(seen_items.entrySet()); required_resolve.sort((a, b) -> Integer.compare(0, a.getValue().compareTo(b.getValue()))); diff --git a/src/main/java/ru/dbotthepony/mc/otm/Registry.java b/src/main/java/ru/dbotthepony/mc/otm/Registry.java index 991e8ff00..374e47472 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/Registry.java +++ b/src/main/java/ru/dbotthepony/mc/otm/Registry.java @@ -17,14 +17,18 @@ import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import ru.dbotthepony.mc.otm.block.BlockAndroidStation; import ru.dbotthepony.mc.otm.block.BlockBatteryBank; +import ru.dbotthepony.mc.otm.block.BlockMatterDecomposer; import ru.dbotthepony.mc.otm.block.entity.BlockEntityAndroidStation; import ru.dbotthepony.mc.otm.block.entity.BlockEntityBatteryBank; +import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterDecomposer; import ru.dbotthepony.mc.otm.item.ItemBattery; import ru.dbotthepony.mc.otm.item.ItemPill; import ru.dbotthepony.mc.otm.menu.AndroidStationMenu; import ru.dbotthepony.mc.otm.menu.BatteryBankMenu; +import ru.dbotthepony.mc.otm.menu.MatterDecomposerMenu; import ru.dbotthepony.mc.otm.screen.AndroidStationScreen; import ru.dbotthepony.mc.otm.screen.BatteryBankScreen; +import ru.dbotthepony.mc.otm.screen.MatterDecomposerScreen; import java.math.BigDecimal; @@ -40,6 +44,8 @@ public class Registry { public static class Names { public static final ResourceLocation ANDROID_STATION = new ResourceLocation(OverdriveThatMatters.MOD_ID, "android_station"); public static final ResourceLocation BATTERY_BANK = new ResourceLocation(OverdriveThatMatters.MOD_ID, "battery_bank"); + public static final ResourceLocation MATTER_DECOMPOSER = new ResourceLocation(OverdriveThatMatters.MOD_ID, "matter_decomposer"); + public static final ResourceLocation ANDROID_CAPABILITY = new ResourceLocation(OverdriveThatMatters.MOD_ID, "android_capability"); public static final ResourceLocation PILL_ANDROID = new ResourceLocation(OverdriveThatMatters.MOD_ID, "pill_android"); @@ -56,15 +62,18 @@ public class Registry { public static class Blocks { public static final Block ANDROID_STATION = new BlockAndroidStation(); public static final Block BATTERY_BANK = new BlockBatteryBank(); + public static final Block MATTER_DECOMPOSER = new BlockMatterDecomposer(); static { ANDROID_STATION.setRegistryName(Names.ANDROID_STATION); BATTERY_BANK.setRegistryName(Names.BATTERY_BANK); + MATTER_DECOMPOSER.setRegistryName(Names.MATTER_DECOMPOSER); } public static void register(final RegistryEvent.Register event) { event.getRegistry().register(ANDROID_STATION); event.getRegistry().register(BATTERY_BANK); + event.getRegistry().register(MATTER_DECOMPOSER); // OverdriveThatMatters.LOGGER.info("Registered blocks"); } @@ -73,6 +82,7 @@ public class Registry { public static class Items { public static final Item ANDROID_STATION = new BlockItem(Blocks.ANDROID_STATION, new Item.Properties().stacksTo(64).tab(CreativeModeTab.TAB_MISC)); public static final Item BATTERY_BANK = new BlockItem(Blocks.BATTERY_BANK, new Item.Properties().stacksTo(64).tab(CreativeModeTab.TAB_MISC)); + public static final Item MATTER_DECOMPOSER = new BlockItem(Blocks.MATTER_DECOMPOSER, new Item.Properties().stacksTo(64).tab(CreativeModeTab.TAB_MISC)); public static final ItemPill PILL_ANDROID = new ItemPill(ItemPill.PillType.BECOME_ANDROID); public static final ItemPill PILL_HUMANE = new ItemPill(ItemPill.PillType.BECOME_HUMANE); @@ -86,6 +96,7 @@ public class Registry { static { ANDROID_STATION.setRegistryName(Names.ANDROID_STATION); BATTERY_BANK.setRegistryName(Names.BATTERY_BANK); + MATTER_DECOMPOSER.setRegistryName(Names.MATTER_DECOMPOSER); PILL_ANDROID.setRegistryName(Names.PILL_ANDROID); PILL_HUMANE.setRegistryName(Names.PILL_HUMANE); @@ -100,6 +111,7 @@ public class Registry { public static void register(final RegistryEvent.Register event) { event.getRegistry().register(ANDROID_STATION); event.getRegistry().register(BATTERY_BANK); + event.getRegistry().register(MATTER_DECOMPOSER); event.getRegistry().register(PILL_ANDROID); event.getRegistry().register(PILL_HUMANE); @@ -117,15 +129,18 @@ public class Registry { public static class BlockEntities { public static BlockEntityType ANDROID_STATION = BlockEntityType.Builder.of(BlockEntityAndroidStation::new, Blocks.ANDROID_STATION).build(null); public static BlockEntityType BATTERY_BANK = BlockEntityType.Builder.of(BlockEntityBatteryBank::new, Blocks.BATTERY_BANK).build(null); + public static BlockEntityType MATTER_DECOMPOSER = BlockEntityType.Builder.of(BlockEntityMatterDecomposer::new, Blocks.MATTER_DECOMPOSER).build(null); static { ANDROID_STATION.setRegistryName(Names.ANDROID_STATION); BATTERY_BANK.setRegistryName(Names.BATTERY_BANK); + MATTER_DECOMPOSER.setRegistryName(Names.MATTER_DECOMPOSER); } public static void register(final RegistryEvent.Register> event) { event.getRegistry().register(ANDROID_STATION); event.getRegistry().register(BATTERY_BANK); + event.getRegistry().register(MATTER_DECOMPOSER); // OverdriveThatMatters.LOGGER.info("Registered block entities"); } @@ -134,15 +149,18 @@ public class Registry { public static class Menus { public static final MenuType ANDROID_STATION = new MenuType<>(AndroidStationMenu::new); public static final MenuType BATTERY_BANK = new MenuType<>(BatteryBankMenu::new); + public static final MenuType MATTER_DECOMPOSER = new MenuType<>(MatterDecomposerMenu::new); static { ANDROID_STATION.setRegistryName(Names.ANDROID_STATION); BATTERY_BANK.setRegistryName(Names.BATTERY_BANK); + MATTER_DECOMPOSER.setRegistryName(Names.MATTER_DECOMPOSER); } public static void register(final RegistryEvent.Register> event) { event.getRegistry().register(ANDROID_STATION); event.getRegistry().register(BATTERY_BANK); + event.getRegistry().register(MATTER_DECOMPOSER); // OverdriveThatMatters.LOGGER.info("Registered menus"); } @@ -150,6 +168,7 @@ public class Registry { public static void registerScreens(final FMLClientSetupEvent event) { MenuScreens.register(ANDROID_STATION, AndroidStationScreen::new); MenuScreens.register(BATTERY_BANK, BatteryBankScreen::new); + MenuScreens.register(MATTER_DECOMPOSER, MatterDecomposerScreen::new); // OverdriveThatMatters.LOGGER.info("Registered screens"); } diff --git a/src/main/java/ru/dbotthepony/mc/otm/block/BlockMatterDecomposer.java b/src/main/java/ru/dbotthepony/mc/otm/block/BlockMatterDecomposer.java new file mode 100644 index 000000000..d05bc29d6 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/block/BlockMatterDecomposer.java @@ -0,0 +1,27 @@ +package ru.dbotthepony.mc.otm.block; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.EntityBlock; +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.BlockState; +import ru.dbotthepony.mc.otm.Registry; +import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterDecomposer; + +import javax.annotation.Nullable; + +public class BlockMatterDecomposer extends BlockMatteryRotatableMachineBase implements EntityBlock { + @Nullable + @Override + public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) { + return new BlockEntityMatterDecomposer(blockPos, blockState); + } + + @Nullable + @Override + public BlockEntityTicker getTicker(Level p_153212_, BlockState p_153213_, BlockEntityType p_153214_) { + return p_153212_.isClientSide || p_153214_ != Registry.BlockEntities.MATTER_DECOMPOSER ? null : BlockEntityMatterDecomposer::tick; + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityAndroidStation.java b/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityAndroidStation.java index efd62b3d5..21bc6509d 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityAndroidStation.java +++ b/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityAndroidStation.java @@ -39,7 +39,6 @@ public class BlockEntityAndroidStation extends BlockEntityMatteryPoweredMachine public BlockEntityAndroidStation(BlockPos p_155229_, BlockState p_155230_) { super(Registry.BlockEntities.ANDROID_STATION, p_155229_, p_155230_); energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new BigDecimal(100_000), new BigDecimal(250), new BigDecimal(250)); - energy_resolver = LazyOptional.of(() -> energy); } public static void tick(Level level, BlockPos blockPos, BlockState blockState, T t) { diff --git a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityBatteryBank.java b/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityBatteryBank.java index 2f4f43422..37867959c 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityBatteryBank.java +++ b/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityBatteryBank.java @@ -70,25 +70,15 @@ public class BlockEntityBatteryBank extends BlockEntityMatteryMachine { } @Override - public boolean canExtractOuter() { + public boolean canExtract() { return mode == BankMode.EXTRACT || mode == BankMode.BIDIRECTIONAL; } @Override - public boolean canReceiveOuter() { + public boolean canReceive() { return mode == BankMode.RECEIVE || mode == BankMode.BIDIRECTIONAL; } - @Override - public boolean canExtractInner() { - return true; - } - - @Override - public boolean canReceiveInner() { - return true; - } - @Nonnull @Override public BigDecimal extractEnergyOuter(BigDecimal howMuch, boolean simulate) { @@ -318,7 +308,7 @@ public class BlockEntityBatteryBank extends BlockEntityMatteryMachine { Optional cap = get_entity.getCapability(MatteryCapability.ENERGY).resolve(); if (cap.isPresent()) { - if (cap.get().canReceiveOuter()) { + if (cap.get().canReceive()) { BatteryBankDistribution distribution = tile.energy.getDistribution(false); BigDecimal diff = cap.get().receiveEnergyOuter(distribution.max_throughput, true); diff = tile.energy.extractEnergyOuter(diff, false); diff --git a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterDecomposer.java b/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterDecomposer.java new file mode 100644 index 000000000..d59bf07a4 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterDecomposer.java @@ -0,0 +1,243 @@ +package ru.dbotthepony.mc.otm.block.entity; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TranslatableComponent; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +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.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import ru.dbotthepony.mc.otm.MatterRegistry; +import ru.dbotthepony.mc.otm.OverdriveThatMatters; +import ru.dbotthepony.mc.otm.Registry; +import ru.dbotthepony.mc.otm.capability.IMatterHandler; +import ru.dbotthepony.mc.otm.capability.MatterHandlerCapability; +import ru.dbotthepony.mc.otm.capability.MatteryCapability; +import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage; +import ru.dbotthepony.mc.otm.container.SimpleSerializableContainer; +import ru.dbotthepony.mc.otm.menu.MatterDecomposerMenu; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.math.BigDecimal; + +public class BlockEntityMatterDecomposer extends BlockEntityMatteryPoweredMachine implements IItemHandler { + private static final TranslatableComponent MACHINE_NAME = new TranslatableComponent("block.overdrive_that_matters.matter_decomposer"); + private boolean valid = true; + public final MatterHandlerCapability matter = new MatterHandlerCapability(this::setChanged, IMatterHandler.MatterDirection.EXTRACT, new BigDecimal("20")); + private final LazyOptional matter_resolver = LazyOptional.of(() -> matter); + private final LazyOptional handler_resolver = LazyOptional.of(() -> this); + + // вход, выход + public SimpleSerializableContainer item_container = new SimpleSerializableContainer(this::setChanged, 2); + + public BlockEntityMatterDecomposer(BlockPos p_155229_, BlockState p_155230_) { + super(Registry.BlockEntities.MATTER_DECOMPOSER, p_155229_, p_155230_); + energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new BigDecimal(400_000), new BigDecimal(2000), new BigDecimal(2000)); + } + + @Override + public int getSlots() { + return item_container.getContainerSize(); + } + + @Nonnull + @Override + public ItemStack getStackInSlot(int slot) { + return item_container.getItem(slot); + } + + @Nonnull + @Override + public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { + if (slot != 0) + return stack; + + if (!MatterRegistry.hasMatterValue(stack)) + return stack; + + ItemStack self_stack = item_container.getItem(slot); + + if (self_stack.isEmpty()) { + if (!simulate) { + item_container.setItem(slot, stack.copy()); + } + + return ItemStack.EMPTY; + } else if (self_stack.isStackable() && self_stack.getMaxStackSize() > self_stack.getCount() && ItemStack.isSameItemSameTags(self_stack, stack)) { + int new_count = Math.min(self_stack.getMaxStackSize(), self_stack.getCount() + stack.getCount()); + int diff = new_count - self_stack.getCount(); + + if (diff != 0) { + if (!simulate) { + self_stack.grow(diff); + item_container.setChanged(); + } + + ItemStack copy = stack.copy(); + copy.shrink(diff); + return copy; + } + } + + return stack; + } + + @Nonnull + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + if (slot != 1 || amount == 0) + return ItemStack.EMPTY.copy(); + + if (amount < 0) + throw new IllegalArgumentException("Can not extract negative amount of items"); + + ItemStack self_stack = item_container.getItem(slot); + + if (self_stack.isEmpty()) + return ItemStack.EMPTY.copy(); + + int minimal = Math.min(amount, self_stack.getCount()); + ItemStack copy = self_stack.copy(); + copy.setCount(minimal); + + if (!simulate) { + self_stack.shrink(minimal); + item_container.setChanged(); + } + + return copy; + } + + @Override + public int getSlotLimit(int slot) { + // return Items.AIR.getMaxStackSize(); + return item_container.getMaxStackSize(); + } + + @Override + public boolean isItemValid(int slot, @Nonnull ItemStack stack) { + return slot == 0 && MatterRegistry.hasMatterValue(stack); + } + + @Override + protected Component getDefaultDisplayName() { + return MACHINE_NAME; + } + + @Nullable + @Override + public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) { + return new MatterDecomposerMenu(containerID, inventory, this); + } + + @Override + public CompoundTag save(CompoundTag nbt) { + nbt.put("work_inventory", item_container.serializeNBT()); + nbt.putDouble("work_progress", work_progress); + nbt.put("work_item", work_item.serializeNBT()); + + nbt.put("matter_capability", matter.serializeNBT()); + + return super.save(nbt); + } + + @Override + public void load(CompoundTag nbt) { + super.load(nbt); + + if (nbt.contains("matter_capability") && nbt.get("matter_capability") instanceof CompoundTag tag) + matter.deserializeNBT(tag); + + if (nbt.contains("work_inventory") && nbt.get("work_inventory") instanceof CompoundTag tag) + item_container = SimpleSerializableContainer.of(this::setChanged, tag, item_container.getContainerSize()); + + work_progress = nbt.getDouble("work_progress"); + + if (nbt.contains("work_item") && nbt.get("work_item") instanceof CompoundTag tag) + work_item = ItemStack.of(tag); + } + + @Override + public void reviveCaps() { + valid = true; + super.reviveCaps(); + } + + @Override + public void invalidateCaps() { + valid = false; + super.invalidateCaps(); + } + + @Nonnull + @Override + public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { + if (valid) { + if (cap == MatteryCapability.MATTER) + return matter_resolver.cast(); + + if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) + return handler_resolver.cast(); + } + + return super.getCapability(cap, side); + } + + private static final BigDecimal ENERGY_CONSUMPTION_PER_TICK = new BigDecimal("240"); + + private double work_progress = 0; + private ItemStack work_item = ItemStack.EMPTY; + + public double getWorkProgress() { + return work_progress; + } + + public static void tick(Level level, BlockPos blockPos, BlockState blockState, T t) { + if (t instanceof BlockEntityMatterDecomposer tile) { + tile.tickBatteryCharge(); + + ItemStack stack = tile.item_container.getItem(0); + + if (!stack.isEmpty()) { + BigDecimal matter_value = MatterRegistry.getMatterValue(stack); + + if (!matter_value.equals(BigDecimal.ZERO) && tile.matter.canReceiveAll(matter_value)) { + if (!ItemStack.isSameItemSameTags(tile.work_item, stack)) { + tile.work_progress = 0; + tile.work_item = stack.copy(); + } + + tile.work_progress += + // work speed multiplier + tile.workSpeedMultiplier(ENERGY_CONSUMPTION_PER_TICK) * + // unit of full work for getting thing done (0.05 MtU is full unit of work, which is equal one real second) + // the more MtUs are in item, the lesser this value should be + (0.05 / matter_value.doubleValue()) * + // the tick time + 0.05; + + if (tile.work_progress >= 1) { + // work is done! + tile.matter.receiveMatterInner(matter_value, false); + stack.shrink(1); + tile.item_container.setChanged(); + tile.work_progress = 0; + } + } + } else if (tile.work_progress != 0) { + tile.work_progress = 0; + tile.work_item = ItemStack.EMPTY; + } + } + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatteryPoweredMachine.java b/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatteryPoweredMachine.java index e262bb8d6..d1aaa01f7 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatteryPoweredMachine.java +++ b/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatteryPoweredMachine.java @@ -5,6 +5,7 @@ import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.StringTag; import net.minecraft.network.chat.Component; +import net.minecraft.world.Container; import net.minecraft.world.SimpleContainer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntityType; @@ -25,12 +26,24 @@ import java.util.Optional; abstract public class BlockEntityMatteryPoweredMachine extends BlockEntityMatteryMachine { protected MatteryMachineEnergyStorage energy = null; - protected LazyOptional energy_resolver = null; + protected final LazyOptional energy_resolver = LazyOptional.of(() -> energy);; private boolean valid = true; public SimpleSerializableContainer battery_container = new SimpleSerializableContainer(this::setChanged, 1); + protected double workSpeedMultiplier(BigDecimal energy_required, boolean simulate) { + BigDecimal extract_much = energy.extractEnergyInner(energy_required, simulate); + return extract_much.divide(energy_required, MatteryCapability.ROUND_RULES).doubleValue(); + } + + protected double workSpeedMultiplier(BigDecimal energy_required) { + return workSpeedMultiplier(energy_required, false); + } + protected void tickBatteryCharge() { + if (energy == null) + return; + if (energy.getMissingPower().compareTo(BigDecimal.ZERO) <= 0) return; @@ -96,7 +109,7 @@ abstract public class BlockEntityMatteryPoweredMachine extends BlockEntityMatter @Nonnull public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { - if (valid && (cap == MatteryCapability.ENERGY || cap == CapabilityEnergy.ENERGY) && energy_resolver != null) { + if (valid && (cap == MatteryCapability.ENERGY || cap == CapabilityEnergy.ENERGY) && energy != null) { return energy_resolver.cast(); } diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/IMatterHandler.java b/src/main/java/ru/dbotthepony/mc/otm/capability/IMatterHandler.java new file mode 100644 index 000000000..eb71a869b --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/IMatterHandler.java @@ -0,0 +1,30 @@ +package ru.dbotthepony.mc.otm.capability; + +import javax.annotation.Nonnull; +import java.math.BigDecimal; + +public interface IMatterHandler { + enum MatterDirection { + RECEIVE, // consumer + EXTRACT, // producer + BIDIRECTIONAL // storage + } + + @Nonnull + BigDecimal getStoredMatter(); + @Nonnull + BigDecimal getMaxStoredMatter(); + + @Nonnull + BigDecimal receiveMatterOuter(BigDecimal howMuch, boolean simulate); + @Nonnull + BigDecimal receiveMatterInner(BigDecimal howMuch, boolean simulate); + + @Nonnull + BigDecimal extractMatterOuter(BigDecimal howMuch, boolean simulate); + @Nonnull + BigDecimal extractMatterInner(BigDecimal howMuch, boolean simulate); + + @Nonnull + MatterDirection getDirection(); +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/IMatteryEnergyStorage.java b/src/main/java/ru/dbotthepony/mc/otm/capability/IMatteryEnergyStorage.java index d8a61bb61..bbb79fa96 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/IMatteryEnergyStorage.java +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/IMatteryEnergyStorage.java @@ -132,20 +132,4 @@ public interface IMatteryEnergyStorage extends IEnergyStorage { default boolean canReceive() { return receiveEnergyOuter(BigDecimal.ONE, true).compareTo(BigDecimal.ZERO) > 0; }; - - default boolean canExtractOuter() { - return extractEnergyOuter(BigDecimal.ONE, true).compareTo(BigDecimal.ZERO) > 0; - }; - - default boolean canReceiveOuter() { - return receiveEnergyOuter(BigDecimal.ONE, true).compareTo(BigDecimal.ZERO) > 0; - }; - - default boolean canExtractInner() { - return extractEnergyInner(BigDecimal.ONE, true).compareTo(BigDecimal.ZERO) > 0; - }; - - default boolean canReceiveInner() { - return receiveEnergyInner(BigDecimal.ONE, true).compareTo(BigDecimal.ZERO) > 0; - }; } diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/MatterHandlerCapability.java b/src/main/java/ru/dbotthepony/mc/otm/capability/MatterHandlerCapability.java new file mode 100644 index 000000000..ca5cc0f7a --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/MatterHandlerCapability.java @@ -0,0 +1,164 @@ +package ru.dbotthepony.mc.otm.capability; + +import net.minecraft.nbt.CompoundTag; +import net.minecraftforge.common.util.INBTSerializable; +import ru.dbotthepony.mc.otm.MatterRegistry; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.math.BigDecimal; + +public class MatterHandlerCapability implements IMatterHandler, INBTSerializable { + protected final Runnable listener; + protected BigDecimal stored = BigDecimal.ZERO; + protected MatterDirection direction; + protected BigDecimal max_storage; + + protected BigDecimal max_receive; + protected BigDecimal max_extract; + + public MatterHandlerCapability( + @Nullable Runnable listener, + MatterDirection direction, + BigDecimal max_storage + ) { + this.listener = listener; + this.direction = direction; + this.max_storage = max_storage; + } + + public MatterHandlerCapability( + @Nullable Runnable listener, + MatterDirection direction, + BigDecimal max_storage, + BigDecimal max_receive, + BigDecimal max_extract + ) { + this(listener, direction, max_storage); + + this.max_receive = max_receive; + this.max_extract = max_extract; + } + + @Nonnull + @Override + public BigDecimal getStoredMatter() { + return stored; + } + + @Nonnull + @Override + public BigDecimal getMaxStoredMatter() { + return max_storage; + } + + public boolean canReceiveAll(BigDecimal value) { + return max_storage.compareTo(value) >= 0 && stored.add(value).compareTo(max_storage) <= 0; + } + + @Nonnull + @Override + public BigDecimal receiveMatterOuter(BigDecimal howMuch, boolean simulate) { + if (direction == MatterDirection.EXTRACT) + return BigDecimal.ZERO; + + return receiveMatterInner(howMuch, simulate); + } + + @Nonnull + @Override + public BigDecimal receiveMatterInner(BigDecimal howMuch, boolean simulate) { + BigDecimal new_matter; + + if (max_receive == null) { + new_matter = stored.add(howMuch, MatterRegistry.ROUND_RULES).min(max_storage); + } else { + new_matter = stored.add(howMuch.min(max_receive), MatterRegistry.ROUND_RULES).min(max_storage); + } + + BigDecimal diff = new_matter.subtract(stored); + + if (!simulate && new_matter.compareTo(stored) != 0) { + stored = new_matter; + + if (listener != null) { + listener.run(); + } + } + + return diff; + } + + @Nonnull + @Override + public BigDecimal extractMatterOuter(BigDecimal howMuch, boolean simulate) { + if (direction == MatterDirection.RECEIVE) + return BigDecimal.ZERO; + + return extractMatterInner(howMuch, simulate); + } + + @Nonnull + @Override + public BigDecimal extractMatterInner(BigDecimal howMuch, boolean simulate) { + BigDecimal new_matter; + + if (max_receive == null) { + new_matter = stored.subtract(howMuch, MatterRegistry.ROUND_RULES).max(BigDecimal.ZERO); + } else { + new_matter = stored.subtract(howMuch.min(max_receive), MatterRegistry.ROUND_RULES).max(BigDecimal.ZERO); + } + + BigDecimal diff = stored.subtract(new_matter); + + if (!simulate && new_matter.compareTo(stored) != 0) { + stored = new_matter; + + if (listener != null) { + listener.run(); + } + } + + return diff; + } + + @Nonnull + @Override + public MatterDirection getDirection() { + return direction; + } + + @Override + public CompoundTag serializeNBT() { + CompoundTag tag = new CompoundTag(); + tag.putString("stored", stored.toString()); + tag.putString("max_storage", max_storage.toString()); + + if (max_receive != null) + tag.putString("max_receive", max_receive.toString()); + + if (max_extract != null) + tag.putString("max_extract", max_extract.toString()); + + return tag; + } + + @Override + public void deserializeNBT(CompoundTag tag) { + if (tag.contains("stored")) + stored = new BigDecimal(tag.getString("stored")); + + if (tag.contains("max_storage")) + max_storage = new BigDecimal(tag.getString("max_storage")); + + if (tag.contains("max_receive")) + max_receive = new BigDecimal(tag.getString("max_receive")); + else + max_receive = null; + + if (tag.contains("max_extract")) + max_extract = new BigDecimal(tag.getString("max_extract")); + else + max_extract = null; + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java b/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java index 47fbb295e..3e99dd865 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java @@ -16,12 +16,17 @@ public class MatteryCapability { @CapabilityInject(IAndroidCapability.class) public static Capability ANDROID = null; + @CapabilityInject(IMatterHandler.class) + public static Capability MATTER = null; + public static void register() { CapabilityManager.INSTANCE.register(IAndroidCapability.class); CapabilityManager.INSTANCE.register(IMatteryEnergyStorage.class); + + CapabilityManager.INSTANCE.register(IMatterHandler.class); } - public static final MathContext ROUND_RULES = new MathContext(24, RoundingMode.HALF_UP); + public static final MathContext ROUND_RULES = new MathContext(32, RoundingMode.HALF_DOWN); public static final BigDecimal INT_MAX_VALUE = new BigDecimal(Integer.MAX_VALUE); public static final BigDecimal INT_MIN_VALUE = new BigDecimal(Integer.MIN_VALUE); diff --git a/src/main/java/ru/dbotthepony/mc/otm/item/ItemBattery.java b/src/main/java/ru/dbotthepony/mc/otm/item/ItemBattery.java index 2e0614de7..d6d00f342 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/item/ItemBattery.java +++ b/src/main/java/ru/dbotthepony/mc/otm/item/ItemBattery.java @@ -7,9 +7,12 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.world.item.*; import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.energy.CapabilityEnergy; +import net.minecraftforge.fml.loading.FMLEnvironment; import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage; import ru.dbotthepony.mc.otm.capability.MatteryCapability; import ru.dbotthepony.mc.otm.menu.FormattingHelper; @@ -18,6 +21,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.math.BigDecimal; import java.util.List; +import java.util.Objects; public class ItemBattery extends Item { public class BatteryMatteryCapability implements IMatteryEnergyStorage, ICapabilityProvider { @@ -25,19 +29,32 @@ public class ItemBattery extends Item { private final BigDecimal max_input; private final BigDecimal max_output; private final boolean is_creative; + private BigDecimal energy; + private String _energy; private final ItemStack stack; private BigDecimal energy() { CompoundTag tag = stack.getOrCreateTag(); - if (tag.contains("otm_energy")) - return new BigDecimal(tag.getString("otm_energy")); + if (tag.contains("otm_energy")) { + String get_energy = tag.getString("otm_energy"); + + if (Objects.equals(_energy, get_energy)) { + return energy; + } + + energy = new BigDecimal(tag.getString("otm_energy")); + _energy = get_energy; + + return energy; + } return BigDecimal.ZERO; } private void energy(BigDecimal value) { + energy = value; stack.getOrCreateTag().putString("otm_energy", value.toString()); } @@ -132,7 +149,7 @@ public class ItemBattery extends Item { @Nonnull @Override public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { - if (cap == MatteryCapability.ENERGY) + if (cap == MatteryCapability.ENERGY || cap == CapabilityEnergy.ENERGY) return resolver.cast(); return LazyOptional.empty(); @@ -147,26 +164,6 @@ public class ItemBattery extends Item { public boolean canReceive() { return true; } - - @Override - public boolean canExtractOuter() { - return true; - } - - @Override - public boolean canReceiveOuter() { - return true; - } - - @Override - public boolean canExtractInner() { - return true; - } - - @Override - public boolean canReceiveInner() { - return true; - } } private final boolean is_creative; diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.java b/src/main/java/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.java index d3ef1033e..517d850b6 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.java +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/AndroidStationMenu.java @@ -35,7 +35,7 @@ public class AndroidStationMenu extends PoweredMatteryMenu { private final IAndroidCapability android; public AndroidBatterySlot(AndroidStationContainer container, int index, int x, int y) { - super(container, index, x, y); + super(container, index, x, y, false); android = container.android; } diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/FormattingHelper.java b/src/main/java/ru/dbotthepony/mc/otm/menu/FormattingHelper.java index ebc23139f..2bbb81df1 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/FormattingHelper.java +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/FormattingHelper.java @@ -70,10 +70,18 @@ public class FormattingHelper { return new TranslatableComponent("otm.gui.level", formatSI(power, POWER_NAME), formatSI(max_power, POWER_NAME)); } + public static Component formatMatterLevel(BigDecimal power, BigDecimal max_power) { + return new TranslatableComponent("otm.gui.level", formatMatterValuePlain(power), formatMatterValuePlain(max_power)); + } + public static TranslatableComponent formatMatterValue(BigDecimal matter) { return new TranslatableComponent("otm.gui.matter.format", formatSI(matter, MATTER_NAME)); } + public static Component formatMatterValuePlain(BigDecimal matter) { + return formatSI(matter, MATTER_NAME); + } + public static Component formatPower(BigDecimal power) { return formatSI(power, POWER_NAME); } diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/MatterDecomposerMenu.java b/src/main/java/ru/dbotthepony/mc/otm/menu/MatterDecomposerMenu.java new file mode 100644 index 000000000..6dafeb658 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/MatterDecomposerMenu.java @@ -0,0 +1,105 @@ +package ru.dbotthepony.mc.otm.menu; + +import net.minecraft.world.Container; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.ContainerData; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import ru.dbotthepony.mc.otm.MatterRegistry; +import ru.dbotthepony.mc.otm.Registry; +import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterDecomposer; +import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatteryPoweredMachine; +import ru.dbotthepony.mc.otm.menu.data.BigDecimalDataContainer; +import ru.dbotthepony.mc.otm.menu.slot.MachineInputSlot; +import ru.dbotthepony.mc.otm.menu.slot.MachineOutputSlot; + +import javax.annotation.Nullable; + +public class MatterDecomposerMenu extends PoweredMatteryMenu { + public MatterDecomposerMenu(int containerID, Inventory inventory) { + this(containerID, inventory, null); + } + + public BigDecimalDataContainer matter; + public BigDecimalDataContainer max_matter; + + public ContainerData progress; + + public MatterDecomposerMenu(int containerID, Inventory inventory, @Nullable BlockEntityMatterDecomposer tile) { + super(Registry.Menus.MATTER_DECOMPOSER, containerID, inventory, tile); + Container container = tile != null ? tile.item_container : new SimpleContainer(2); + + progress = new ContainerData() { + int get_value; + + @Override + public int get(int i) { + if (tile != null) + return (int) (tile.getWorkProgress() * 100); + + return get_value; + } + + @Override + public void set(int i, int i1) { + get_value = i1; + } + + @Override + public int getCount() { + return 1; + } + }; + + // Вход + addSlot(new MachineInputSlot(container, 0, 61, 36) { + @Override + public boolean mayPlace(ItemStack p_40231_) { + return MatterRegistry.hasMatterValue(p_40231_); + } + }); + + // Выход + addSlot(new MachineOutputSlot(container, 1, 61 + 18 + 10 + 3 + 22, 36, true, true)); + + if (tile == null) { + matter = new BigDecimalDataContainer(); + max_matter = new BigDecimalDataContainer(); + } else { + matter = new BigDecimalDataContainer() { + @Override + protected void updateValue() { + setDecimal(tile.matter.getStoredMatter()); + } + }; + + max_matter = new BigDecimalDataContainer() { + @Override + protected void updateValue() { + setDecimal(tile.matter.getMaxStoredMatter()); + } + }; + } + + addBatterySlot(14); + + addInventorySlots(); + + this.addDataSlots(matter); + this.addDataSlots(max_matter); + + this.addDataSlots(progress); + } + + @Override + protected int getWorkingSlotStart() { + return 0; + } + + @Override + protected int getWorkingSlotEnd() { + return 1; + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/PoweredMatteryMenu.java b/src/main/java/ru/dbotthepony/mc/otm/menu/PoweredMatteryMenu.java index dc067b296..8d4d76c0f 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/PoweredMatteryMenu.java +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/PoweredMatteryMenu.java @@ -4,7 +4,9 @@ import net.minecraft.world.Container; import net.minecraft.world.SimpleContainer; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.item.ItemStack; import net.minecraftforge.common.util.LazyOptional; +import ru.dbotthepony.mc.otm.OverdriveThatMatters; import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatteryPoweredMachine; import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage; import ru.dbotthepony.mc.otm.capability.MatteryCapability; @@ -26,6 +28,7 @@ abstract public class PoweredMatteryMenu extends MatteryMenu { @Nullable BlockEntityMatteryPoweredMachine tile ) { super(menuType, containerID, inventory, tile); + this.tile = tile; if (tile == null) { energy = new BigDecimalDataContainer(); @@ -60,8 +63,12 @@ abstract public class PoweredMatteryMenu extends MatteryMenu { addBatterySlot(8, 66); } + protected void addBatterySlot(int x) { + addBatterySlot(x, 66); + } + protected void addBatterySlot(int x, int y) { Container battery_container = tile != null ? tile.battery_container : new SimpleContainer(1); - this.addSlot(new BatterySlot(battery_container, 0, x, y)); + this.addSlot(new BatterySlot(battery_container, 0, x, y, true)); } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/slot/BatterySlot.java b/src/main/java/ru/dbotthepony/mc/otm/menu/slot/BatterySlot.java index b4e43a081..a01fb2b1d 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/slot/BatterySlot.java +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/slot/BatterySlot.java @@ -12,18 +12,19 @@ import ru.dbotthepony.mc.otm.capability.MatteryCapability; import java.util.Optional; public class BatterySlot extends Slot { - public BatterySlot(Container container, int index, int x, int y) { + public boolean auto_bg; + + public BatterySlot(Container container, int index, int x, int y, boolean auto_bg) { super(container, index, x, y); + this.auto_bg = auto_bg; + } + + public BatterySlot(Container container, int index, int x, int y) { + this(container, index, x, y, true); } @Override public boolean mayPlace(ItemStack stack) { - Optional storage = stack.getCapability(MatteryCapability.ENERGY).resolve(); - - if (storage.isPresent()) { - return storage.get().canExtractOuter(); - } - LazyOptional capability = stack.getCapability(CapabilityEnergy.ENERGY); return capability.resolve().isPresent() && capability.resolve().get().canExtract(); } diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/slot/MachineInputSlot.java b/src/main/java/ru/dbotthepony/mc/otm/menu/slot/MachineInputSlot.java new file mode 100644 index 000000000..8374489a2 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/slot/MachineInputSlot.java @@ -0,0 +1,19 @@ +package ru.dbotthepony.mc.otm.menu.slot; + +import net.minecraft.world.Container; +import net.minecraft.world.inventory.Slot; + +// Just a sign that this slot needs auto draw +public class MachineInputSlot extends Slot { + public boolean auto_bg; + + public MachineInputSlot(Container p_40223_, int index, int x, int y, boolean auto_bg) { + super(p_40223_, index, x, y); + this.auto_bg = auto_bg; + } + + public MachineInputSlot(Container p_40223_, int index, int x, int y) { + this(p_40223_, index, x, y, true); + } + +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/slot/MachineOutputSlot.java b/src/main/java/ru/dbotthepony/mc/otm/menu/slot/MachineOutputSlot.java new file mode 100644 index 000000000..5e25b1d71 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/slot/MachineOutputSlot.java @@ -0,0 +1,25 @@ +package ru.dbotthepony.mc.otm.menu.slot; + +import net.minecraft.world.Container; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; + +public class MachineOutputSlot extends Slot { + public boolean auto_bg; + public boolean is_main_output; + + public MachineOutputSlot(Container p_40223_, int index, int x, int y, boolean auto_bg, boolean is_main_output) { + super(p_40223_, index, x, y); + this.is_main_output = is_main_output; + this.auto_bg = auto_bg; + } + + public MachineOutputSlot(Container p_40223_, int index, int x, int y) { + this(p_40223_, index, x, y, true, false); + } + + @Override + public boolean mayPlace(ItemStack p_40231_) { + return false; + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/BatteryBankScreen.java b/src/main/java/ru/dbotthepony/mc/otm/screen/BatteryBankScreen.java index b1d615a3c..7410d9a99 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/screen/BatteryBankScreen.java +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/BatteryBankScreen.java @@ -19,20 +19,10 @@ public class BatteryBankScreen extends MatteryScreen { public BatteryBankScreen(BatteryBankMenu p_97741_, Inventory p_97742_, Component p_97743_) { super(p_97741_, p_97742_, p_97743_); - } + power_supplier = () -> menu.energy.getDecimal(); + max_matter_supplier = () -> menu.max_energy.getDecimal(); - @Override - protected void renderTooltip(PoseStack p_97791_, int mouseX, int mouseY) { - super.renderTooltip(p_97791_, mouseX, mouseY); - - if (this.hoveredSlot == null && menu.getCarried().isEmpty() && hovering_power_gauge) { - this.renderComponentToolTip(p_97791_, getFormattedPowerLevel(() -> menu.energy.getDecimal(), () -> menu.max_energy.getDecimal()), mouseX, mouseY, font); - } - } - - @Override - protected void renderBg(PoseStack pose, float p_97788_, int mouseX, int mouseY) { - super.renderBg(pose, p_97788_, mouseX, mouseY); - renderPowerGauge(pose, 15, 24, mouseX, mouseY, () -> menu.energy.getDecimal(), () -> menu.max_energy.getDecimal()); + power_gauge_x = 15; + power_gauge_y = 24; } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/MatterDecomposerScreen.java b/src/main/java/ru/dbotthepony/mc/otm/screen/MatterDecomposerScreen.java new file mode 100644 index 000000000..70aac663e --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/MatterDecomposerScreen.java @@ -0,0 +1,16 @@ +package ru.dbotthepony.mc.otm.screen; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Inventory; +import ru.dbotthepony.mc.otm.menu.MatterDecomposerMenu; + +public class MatterDecomposerScreen extends PoweredMachineScreen { + public MatterDecomposerScreen(MatterDecomposerMenu p_97741_, Inventory p_97742_, Component p_97743_) { + super(p_97741_, p_97742_, p_97743_); + matter_supplier = () -> menu.matter.getDecimal(); + max_matter_supplier = () -> menu.max_matter.getDecimal(); + + progress_supplier = () -> p_97741_.progress.get(0) / 100f; + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/MatteryScreen.java b/src/main/java/ru/dbotthepony/mc/otm/screen/MatteryScreen.java index ea5a56ab1..b8a2d696e 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/screen/MatteryScreen.java +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/MatteryScreen.java @@ -9,23 +9,50 @@ import net.minecraft.network.chat.FormattedText; import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.Slot; import ru.dbotthepony.mc.otm.OverdriveThatMatters; import ru.dbotthepony.mc.otm.capability.MatteryCapability; import ru.dbotthepony.mc.otm.menu.FormattingHelper; import ru.dbotthepony.mc.otm.menu.MatteryMenu; -import ru.dbotthepony.mc.otm.menu.PoweredMatteryMenu; +import ru.dbotthepony.mc.otm.menu.slot.BatterySlot; +import ru.dbotthepony.mc.otm.menu.slot.MachineInputSlot; +import ru.dbotthepony.mc.otm.menu.slot.MachineOutputSlot; import java.math.BigDecimal; import java.util.List; import java.util.function.Supplier; public class MatteryScreen extends AbstractContainerScreen { - protected static final ResourceLocation CONTAINER_BASE = new ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/mattery_machine_base.png"); + protected static final ResourceLocation CONTAINER_BASE = new ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/generic_machine.png"); + public static final ResourceLocation WIDGETS = new ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets.png"); + + public static final int PROGRESS_WIDGET_WIDTH = 21; + public static final int PROGRESS_WIDGET_HEIGHT = 16; protected ResourceLocation CONTAINER_BACKGROUND() { return CONTAINER_BASE; } + protected Supplier power_supplier; + protected Supplier max_power_supplier; + + protected int power_gauge_x = 13; + protected int power_gauge_y = 14; + + protected Supplier matter_supplier; + protected Supplier max_matter_supplier; + + protected Supplier progress_supplier; + + protected int matter_gauge_x = 22; + protected int matter_gauge_y = 14; + + protected boolean hovering_power_gauge = false; + protected boolean hovering_matter_gauge = false; + + protected int render_x; + protected int render_y; + public MatteryScreen(T p_97741_, Inventory p_97742_, Component p_97743_) { super(p_97741_, p_97742_, p_97743_); @@ -36,75 +63,212 @@ public class MatteryScreen extends AbstractContainerScree inventoryLabelY = imageHeight - 92; } - protected boolean hovering_power_gauge = false; + @Override + protected void renderTooltip(PoseStack p_97791_, int mouseX, int mouseY) { + super.renderTooltip(p_97791_, mouseX, mouseY); - protected List getFormattedPowerLevel(Supplier s_energy, Supplier s_max_energy) { - BigDecimal energy = s_energy.get(); - BigDecimal max_energy = s_max_energy.get(); + if (this.hoveredSlot == null && menu.getCarried().isEmpty()) { + if (hovering_power_gauge) { + List text = getFormattedPowerLevel(); - float level; + if (text.size() != 0) + this.renderComponentToolTip(p_97791_, text, mouseX, mouseY, font); + } else if (hovering_matter_gauge) { + List text = getFormattedMatterLevel(); - if (max_energy.compareTo(BigDecimal.ZERO) == 0) { - level = 0f; - } else { - level = energy.divide(max_energy, MatteryCapability.ROUND_RULES).floatValue(); + if (text.size() != 0) + this.renderComponentToolTip(p_97791_, text, mouseX, mouseY, font); + } } + } + + protected List getFormattedPowerLevel() { + if (power_supplier != null && max_power_supplier != null) + return getFormattedPowerLevel(power_supplier.get(), max_power_supplier.get()); + + return List.of(); + } + + protected List getFormattedMatterLevel() { + if (matter_supplier != null && max_matter_supplier != null) + return getFormattedMatterLevel(matter_supplier.get(), max_matter_supplier.get()); + + return List.of(); + } + + protected List getFormattedPowerLevel(BigDecimal current, BigDecimal max) { + if (current == null || max == null) + return List.of(); return List.of( - new TranslatableComponent("otm.gui.power.percentage_level", String.format("%.2f", level * 100d)), - FormattingHelper.formatPowerLevel(energy, max_energy) + new TranslatableComponent("otm.gui.power.percentage_level", String.format("%.2f", level(current, max) * 100d)), + FormattingHelper.formatPowerLevel(current, max) ); } - protected boolean renderPowerGauge(PoseStack pose, int x, int y, int mouseX, int mouseY, Supplier s_energy, Supplier s_max_energy) { - BigDecimal energy = s_energy.get(); - BigDecimal max_energy = s_max_energy.get(); + protected List getFormattedMatterLevel(BigDecimal current, BigDecimal max) { + if (current == null || max == null) + return List.of(); - int i = (width - imageWidth) / 2; - int j = (height - imageHeight) / 2; + return List.of( + new TranslatableComponent("otm.gui.matter.percentage_level", String.format("%.2f", level(current, max) * 100d)), + FormattingHelper.formatMatterLevel(current, max) + ); + } - float level; + protected void renderVerticalGauge(PoseStack pose, int x, int y, float level, int image_x, int image_y, int width, int max_height) { + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderTexture(0, WIDGETS); - if (max_energy.compareTo(BigDecimal.ZERO) == 0) { - level = 0f; - } else { - level = energy.divide(max_energy, MatteryCapability.ROUND_RULES).floatValue(); + this.blit(pose, render_x + x, render_y + y, image_x, image_y, width, max_height); - if (level >= 0.98) - level = 1f; + if (level > 0.01f) { + int intHeight = (int) Math.floor(level * (float) max_height + 0.5f); + this.blit(pose, render_x + x, render_y + y + max_height - intHeight, image_x + width, image_y + max_height - intHeight, width, intHeight); } + } - if (level > 0.01) { - RenderSystem.setShader(GameRenderer::getPositionTexShader); - RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - RenderSystem.setShaderTexture(0, CONTAINER_BASE); - - int intHeight = (int) Math.floor(level * 46d + 0.5d); - - this.blit(pose, i + x, j + y + 46 - intHeight, 176, 0, 7, intHeight); - } + protected boolean renderVerticalGauge(PoseStack pose, int x, int y, int mouseX, int mouseY, float level, int image_x, int image_y, int width, int max_height) { + renderVerticalGauge(pose, x, y, level, image_x, image_y, width, max_height); x += leftPos; y += topPos; - hovering_power_gauge = x <= mouseX && x + 7 >= mouseX && y <= mouseY && y + 46 >= mouseY; - return hovering_power_gauge; + return x <= mouseX && x + 7 >= mouseX && y <= mouseY && y + 46 >= mouseY; + } + + protected void renderHorizontalGauge(PoseStack pose, int x, int y, float level, int image_x, int image_y, int max_width, int height) { + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderTexture(0, WIDGETS); + + this.blit(pose, render_x + x, render_y + y, image_x, image_y, max_width, height); + + if (level > 0.01f) { + int intWidth = (int) Math.floor(level * (float) max_width + 0.5f); + this.blit(pose, render_x + x, render_y + y, image_x + max_width, image_y, intWidth, height); + } + } + + protected boolean renderHorizontalGauge(PoseStack pose, int x, int y, int mouseX, int mouseY, float level, int image_x, int image_y, int width, int max_height) { + renderVerticalGauge(pose, x, y, level, image_x, image_y, width, max_height); + + x += leftPos; + y += topPos; + return x <= mouseX && x + 7 >= mouseX && y <= mouseY && y + 46 >= mouseY; + } + + public static float level(BigDecimal a, BigDecimal b, boolean exact) { + float level; + + if (b.compareTo(BigDecimal.ZERO) == 0) { + level = 0f; + } else { + level = a.divide(b, MatteryCapability.ROUND_RULES).floatValue(); + + if (!exact && level >= 0.98) + level = 1f; + } + + return level; + } + + public static float level(BigDecimal a, BigDecimal b) { + return level(a, b, true); + } + + protected boolean renderMatterGauge(PoseStack pose, int mouseX, int mouseY) { + if (matter_supplier != null && max_matter_supplier != null) + return renderMatterGauge(pose, mouseX, mouseY, matter_supplier.get(), max_matter_supplier.get()); + + return false; + } + + protected boolean renderPowerGauge(PoseStack pose, int mouseX, int mouseY) { + if (power_supplier != null && max_power_supplier != null) + return renderPowerGauge(pose, mouseX, mouseY, power_supplier.get(), max_power_supplier.get()); + + return false; + } + + protected boolean renderMatterGauge(PoseStack pose, int mouseX, int mouseY, BigDecimal current_value, BigDecimal max_value) { + return renderMatterGauge(pose, matter_gauge_x, matter_gauge_y, mouseX, mouseY, current_value, max_value); + } + + protected boolean renderPowerGauge(PoseStack pose, int mouseX, int mouseY, BigDecimal current_value, BigDecimal max_value) { + return renderPowerGauge(pose, power_gauge_x, power_gauge_y, mouseX, mouseY, current_value, max_value); + } + + protected boolean renderPowerGauge(PoseStack pose, int x, int y, int mouseX, int mouseY, BigDecimal current_value, BigDecimal max_value) { + return hovering_power_gauge = renderVerticalGauge(pose, x, y, mouseX, mouseY, level(current_value, max_value), 0, 48, 9, 48); + } + + protected boolean renderMatterGauge(PoseStack pose, int x, int y, int mouseX, int mouseY, BigDecimal current_value, BigDecimal max_value) { + return hovering_matter_gauge = renderVerticalGauge(pose, x, y, mouseX, mouseY, level(current_value, max_value), 0, 0, 9, 48); + } + + protected void renderProgressGauge(PoseStack pose, int x, int y, float level) { + renderHorizontalGauge(pose, x, y, level, 0, 132, 22, 16); + } + + protected void renderProgressGaugeLeft(PoseStack pose, int x, int y, float level) { + renderHorizontalGauge(pose, x - 22, y, level, 0, 132, 22, 16); } @Override public void render(PoseStack p_98418_, int mouseX, int mouseY, float p_98421_) { + render_x = (width - imageWidth) / 2; + render_y = (height - imageHeight) / 2; + this.renderBackground(p_98418_); super.render(p_98418_, mouseX, mouseY, p_98421_); this.renderTooltip(p_98418_, mouseX, mouseY); } + protected void renderRegularSlot(PoseStack pose, int x, int y) { + this.blit(pose, render_x + x - 1, render_y + y - 1, 0, 96, 18, 18); + } + + protected void renderOutputSlot(PoseStack pose, int x, int y) { + this.blit(pose, render_x + x - 5, render_y + y - 5, 18, 96, 26, 26); + } + + protected void renderBatterySlot(PoseStack pose, int x, int y) { + renderRegularSlot(pose, x, y); + this.blit(pose, render_x + x - 1, render_y + y - 1, 0, 114, 18, 18); + } + @Override protected void renderBg(PoseStack pose, float p_97788_, int mouseX, int mouseY) { RenderSystem.setShader(GameRenderer::getPositionTexShader); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.setShaderTexture(0, CONTAINER_BACKGROUND()); - int i = (width - imageWidth) / 2; - int j = (height - imageHeight) / 2; // PoseStack, x, y, image_start_x, image_start_y, rect_size_x, rect_size_y - this.blit(pose, i, j, 0, 0, this.imageWidth, this.imageHeight); + this.blit(pose, render_x, render_y, 0, 0, this.imageWidth, this.imageHeight); + + renderPowerGauge(pose, mouseX, mouseY); + renderMatterGauge(pose, mouseX, mouseY); + + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderTexture(0, WIDGETS); + + for (Slot slot : menu.slots) { + if (slot instanceof BatterySlot slot1 && slot1.auto_bg) { + renderBatterySlot(pose, slot1.x, slot1.y); + } else if (slot instanceof MachineOutputSlot slot1 && slot1.auto_bg) { + if (slot1.is_main_output) { + renderOutputSlot(pose, slot1.x, slot1.y); + + if (progress_supplier != null) { + renderProgressGaugeLeft(pose, slot1.x - 8, slot1.y, progress_supplier.get()); + } + } else { + renderRegularSlot(pose, slot1.x, slot1.y); + } + } else if (slot instanceof MachineInputSlot slot1 && slot1.auto_bg) { + renderRegularSlot(pose, slot1.x, slot1.y); + } + } } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/PoweredMachineScreen.java b/src/main/java/ru/dbotthepony/mc/otm/screen/PoweredMachineScreen.java index 9816b1864..9db00f381 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/screen/PoweredMachineScreen.java +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/PoweredMachineScreen.java @@ -9,36 +9,9 @@ import ru.dbotthepony.mc.otm.menu.PoweredMatteryMenu; import java.util.List; public class PoweredMachineScreen extends MatteryScreen { - protected boolean auto_draw_gauge = true; - protected int power_gauge_x = 13; - protected int power_gauge_y = 15; - public PoweredMachineScreen(T p_97741_, Inventory p_97742_, Component p_97743_) { super(p_97741_, p_97742_, p_97743_); - } - - @Override - protected void renderTooltip(PoseStack p_97791_, int mouseX, int mouseY) { - super.renderTooltip(p_97791_, mouseX, mouseY); - - if (this.hoveredSlot == null && menu.getCarried().isEmpty() && hovering_power_gauge) { - this.renderComponentToolTip(p_97791_, getFormattedPowerLevel(), mouseX, mouseY, font); - } - } - - protected List getFormattedPowerLevel() { - return getFormattedPowerLevel(() -> menu.energy.getDecimal(), () -> menu.max_energy.getDecimal()); - } - - protected void renderPowerGauge(PoseStack pose, int x, int y, int mouseX, int mouseY) { - renderPowerGauge(pose, x, y, mouseX, mouseY, () -> menu.energy.getDecimal(), () -> menu.max_energy.getDecimal()); - } - - @Override - protected void renderBg(PoseStack pose, float p_97788_, int mouseX, int mouseY) { - super.renderBg(pose, p_97788_, mouseX, mouseY); - - if (auto_draw_gauge) - renderPowerGauge(pose, power_gauge_x, power_gauge_y, mouseX, mouseY); + power_supplier = () -> menu.energy.getDecimal(); + max_power_supplier = () -> menu.max_energy.getDecimal(); } } diff --git a/src/main/resources/assets/overdrive_that_matters/lang/en_us.json b/src/main/resources/assets/overdrive_that_matters/lang/en_us.json index 2c35e5649..fa659cd5a 100644 --- a/src/main/resources/assets/overdrive_that_matters/lang/en_us.json +++ b/src/main/resources/assets/overdrive_that_matters/lang/en_us.json @@ -1,11 +1,12 @@ { "otm.pill.warning": "WARNING: This will INSTANTLY kill you upon ingestion!", - "otm.pill.android": "Take this pill and lose what is holding your back.", + "otm.pill.android": "Take this pill and lose what is holding you back.", "otm.pill.humane": "Take this pill and wake up in bed none the wiser.", "otm.gui.power.percentage_level": "Energy level: %s%%", "otm.gui.level": "%s / %s", "otm.gui.power.name": "MtE", + "otm.gui.matter.percentage_level": "Matter level: %s%%", "otm.gui.matter.format": "Matter: %s", "otm.gui.matter.name": "MtU", @@ -42,6 +43,7 @@ "block.overdrive_that_matters.android_station": "Android station", "block.overdrive_that_matters.battery_bank": "Battery bank", + "block.overdrive_that_matters.matter_decomposer": "Matter decomposer", "item.overdrive_that_matters.pill_android": "Android pill", "item.overdrive_that_matters.pill_humane": "Humane pill", diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/android_station.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/android_station.png index 242cc9cf905606f230a358c28c4fce3cd61fc4c2..b920ebcc008ef239de570dc99fd6f437bc28e40f 100644 GIT binary patch delta 6091 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 X{0|Wb;)l}mP+A{K+i#vJR^kBwMcX=j delta 2197 zcmaF9gt2!Y97iL}9cVYj99T)o*CRZ}gV&wr!J5M%bvliro zD1?zLGbbl93v;qS_$*sNJXRow`= zl`=AMoSa|PY@`hXDCt zz+DSAlY1si07xU5$-NP5raS{XP+Sj)L1qd$C6<(=7F8-Fm8PYo7Ad5qPoBd%fpr5= ziUDLty#R=X0DNW$HrybnJNSaI$N`1;vS8x%j7|(}^=zTUW0DjD4gSxzimF%#$v~j% z{{wx(4a7!33<^F$*SyrC^hyOMaOh2LV4lp#Jz1B{z8;h;kbr-qX!~ zn)?`Pn4W+*gK8AmejKKO!}P>4aG2sy0uBsH1sVVx={RCPr2`bVfvr@*#G$)|NkYBOw<$5avNysoR2`_Aecay50v;n zr=Af=f|bAshB=V(4pioW3qJ0o#N_PsqWsdl6p#?8P68EYpz=`>h$nAgt(p9c!@ph> zse%J(1{(k^_{0Q(0zeS=6+*{@B_V9MS|C?!Aw*1?7fS0xXyr!`S`}I+8N@*NX8aJ^ uVLO96nB{OBBH*(PLI?kZ&~Zzl^j0W+6iQ!((s0LbF64g0wD~ztgDU{G`&wcE diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/battery_bank.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/battery_bank.png deleted file mode 100644 index 8339cb0f2ffe59a1fc17270d1ee35e2e0f4afb46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1647 zcmb_cX;4#F6uvKsA%(D2Vx$QWz^W|L2x`a(7$qSDWmRewlqdzHfsh3h5z51ovMH5f z6*NLrlr|_vQ6piCN@H&h!HSLP7}Ou*fG+^m{0>k%YUt`fyxbDFRVcXm~^j0L!xyvYg#-`xr^Q zH=pyj*4t}fnC5fJHZ|SRgOI^JeU-31hPwaRFZT<~IYOaPppM?O?YAa@(wG{^@hei)q`m-|O(t)uLRV_E67)e(FazT6_!PQDAzssDT7 zGYQ_QrNucuzAEFT?Z|<|V$-jq?A6P@)Yv~#q_(6L(pH=ra}nnJwnXwq8e1>JrkR!6 zl}*-^4k*+Px80VmW|NmL%80a8uCy_>9yJm&eOKQlUa_;0Djkb@t$E{hL5uJ5?u8d` z*0soFEjf~mGxm>=;dOl5SNm-$7;x(AF%wL3M0HQwfn}|ewU0Ud#~16~I0uwa={-v& zyBYl%k%@;u(hiw#$n7V>V__!1qjKGo0i2 zx~$198%~4r{6<m}!r2!BC!~v!L#=3zCrhgrr(?K+HW1W4 z4giM7VXog2+dkCk$#3#8f*W}!^i+gn21S0v(e?!9%M0jg?Q;Fehgrk$x#$OG4nS#P zpuBRjx>#duo@Dpp*Lc-s`PS;9HC)s5<3S0$iK?h7qU7vz<#U(G$iXqqCYLEzVZCvUxMS#o7))w9>XpS*4H1up@2F|q3Xq_YlL0xYN z$p8DVK=FZqyVnVA03rYmtN|E60w`D)Kx!-uxM&7YKormlW?>WpLx2PWSeF6RSPB9g zATSPrF$kQYr=FTh=^1eS19&N+f}`WpUCki` zeN9tEuwvx#w5h*8tD#MrM`xD?Kfrd|fIOsN?7ZTi^!B;pD8=CDXk*|rIB z+xM%*5g>mRC~7V*%MzO=40`SpXVTyI-!Qy`r9NB1#nVs~&b5ab$W*Xq5zvQ5@!XqG zY+Rg3)C%GkzzcbN?G$P!k&Voa0~7#*{{~bxA7kIo6&t`DQMN|dNA7i_V7LRM=sDv4 zZVBs@&1m4iJe%-(w+8PVaraU*HkF8MBwd z`G&)cK5~R!(^e+4<9Z}BS%;h>Q59QSoC!ZM?0o3bysmJtC6b2uH~(W0dSSv#{a2{N zyKmgB5V^@>tj6lzgJrLcpn;w6O1V5;T0-x`=RGO*2!cLK@PUZ|$cWzxM#ThT zg@(#?cuOaHjT~lBS$xb(!kjGd`ZzO`iqI;xs&A_xCgBR(+{jrWiHuF6D z#QYEHF4{v#w8Kt4j#6EGh>-LM(oBK#Gpe yBar?&ZfI4Gu0B{-GYnnNOwO&`2Z8_ZfnBP=yJ@^lis6-0@ diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/generic_machine.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/generic_machine.png new file mode 100644 index 0000000000000000000000000000000000000000..3abf7adc27607067bc765d6b4fa198e5bf664b11 GIT binary patch literal 9230 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

PbO<1O^B!&r*)>cx5qi+SG07OFAJzK z3vGpJ=BeEydvomPyXm=4^QF#NN8*4Vpa$F3fm~PsmMPDkQ;L|=VB+J2)|&W8kd1A5 z)6&{*&dYTlPv-E6GEGB**)x*iro{P4{KtZG<$n{n`wHX3J3}HN0H8(KrN;pR0=-R>n`B_Y7AC zKRy+Md3nxMa5v<6Ep!cdRNTGLJd$FPV&Wh*Ka3BA_X;JCoEOSL#z^>@P|{6KD4zEg;w7^-M2(hK8(!??Tg zoMIyE-Mw-0yuA2%p5Nnh_0ZM*1Kth$iv>I%U_XQhSVBx3?CJ{ss|6OP=7R_M70`cc zfi=M&Rf3JsSa)wPBwEb}?S|v~D+CJphrNflm&;i?C?pu|f_BBLV)0%j{^n9cQ`g`R zi&F|5F|HnGR(P`irisHi{7Kf|VmqBVOXshF;LZQQ{hRjhxt}THwea1k>W=h24Np^5 zp7+$h49XpeLCKsA9grxf_+_LdNCG7e1xa3ZkOU!+()J(+h%^*}fWf3764HNx(saY( z5N=5HDHI-D41>pkNy|_IdLINfQf85L^;24w8h!#6fU81W4N60g6OA*h@m;l4npTq>Q?|mn#Ba zPK+zU5e@cmb3B_kC0s_yKvSL@814DSE%mz`^WT(93JsHXKuIG&QgCq?ND_Ywf=fYBAaN-K z8iBM&z+v#875@Vr>+XQ_MR=i=9Pydrv%$B}SvEX^zsM9iOZyLfUnle_Q{oT_khnBR z0%{^5DI*~*1BLN|eenO_{%1MxBDr>Z!Y+~3jD`r^@}gO@Bhu~ zR~`O0UGVVy>*OEt`!8Mp()EuR_(#hBcGtgj{UZkck@COY^&g{)^3TT|v>W~(kT3pW zX09Jqf`1Sqwb#~A1)Q9Ia+`~i@Dd7-tJkmq0Fd$YO8`jEWWfu`aGJVmWQ*j~WDI;M z8ToiiB1TPBB@_Is3X`u~Zz<9#4u0q|os)9vU^@lH2cvT5Jg zCgI@k)TWV+Tp-_*@5-!M%Sk%I7&C-t1wH=;&%mTlR&Dr^ec=Oa%gLTA9o-LBRi$d5 z)w7F~1u!d+19$*o001H2KQ;KzA^j22|1ad1YxU){-0>P)%(brUAEncgeG}M?{U(uJ zMgohFFb12kPU*O%)a|`Y|7@EQE&}{pBg6nYfa2-vBmc+XOjhB5N=Zf1 zcx%xoV*BXnTh4>ulcV&gv7_wa2QTBJq7W>}C*m5D1fmLx6zuLjLRm<@1mFLOR31Pa z-eCg|dw5St2+f-+`mW5?<@e+}d9q=PWP*r~vG4+{3-MQ)|3`3V;S#sfz5w%ZF!CJ{ZADq597nb zi>;iWiBUQ^7^t(vI;XaK8g<+NRdxb1!^>NL(iYY|^`j=x=$s1W1T;4vs0HY^!C sG%NW6F!|;HP{TKue_{jp4_kYI>>_%62#Z3v{Imk^lez literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/battery_bank.xcf b/src/main/resources/assets/overdrive_that_matters/textures/gui/generic_machine.xcf similarity index 69% rename from src/main/resources/assets/overdrive_that_matters/textures/gui/battery_bank.xcf rename to src/main/resources/assets/overdrive_that_matters/textures/gui/generic_machine.xcf index 7321a995581bac7d51d7175e31e5be4395a1df10..a7143751674cc32b39e6d77a3967e621e891acd3 100644 GIT binary patch delta 809 zcmbP#g|TNg;{+paUPcB61`ZG*Fws^G{jBU zLfzhu%Lb;=j!QworX(?4AulmE)mF*1A~Q|T6J)fWQ)WqVKx$ENVs1fBs*;_B0ub8h zmn7Dw64n5UXr0?XJl#yQcp;EcxDQ5s{M;HQ}clKmjHdHWM@dg?4Z=*{G3vd z+R(hr5}<1csEO(#L6jJv4kGiPfMNkda@KujibflV22EkeCb%Oss}SKO_B|&#`-HHD0gNhf$aiorb2%Fst zA1r*gaB1PIpWjLj3{6juPR=HWXU4`xCzE4Ysucqfr~O?qp!icbc1Vnv!zvT#-@zKfbY;r*P!EhGY zj0PNqR`Lh(5ps0upY`|y`IQygKC}`B8|@Em7en%(YWvCPJGl5Vp1vONFVnH$`j3rc z7gc*-H@Mk4p5`|}{KrmS4CoaFXd{>e^a_`NHljU=WL+BqpjS!(6$;QsFbSwofHtB% z320p#0-&Oki;vpH%4@ZbeudEse zTWYTE!|_xzSL=D0PK!dvQ;N&joV+g6aa!f=rh5((Oc|s*^mTvNyC!o7Kg0y@NsGWx zdwPYZyMq;BMe)GtD#0M=5dc(ET&w|@S=dUbVch8|z+e?z0vP}^m=x$f^*V}P;StH`ZfjX)cxdEwc5-57{3PYJ(n1U!4~6wE#6(qf6Ytq? zBn5&*L%-bH^McCDKB{?tNLi@%{HFB#^a|*{ag{#2SMk)0;*Wi(__5~|fBIj=pCNn^ zUiwGzS07V+?03!oRy?bZE4x#tSC9Qk_JqE!N5tcNnF-P7;<_W?P;Z8pInKQdRRJwXX;BthE-R2=w2M+pk$@Sag&d$Lv=kMz)EH%vEu|GK zB0TO1FAzK;mRHNl%49%RP-U0YF{lbykuO+S2~b%^%UZj_cqH%)$rBT7D~!=8RxZKZ zR#`Pv=*q3vt~`>QI;K7xS&ux@+c_qO9E3v-794VZ5UvMW8l1NsavoaH(!A}EgR;v} zSttX_A?Kw-&O-|_?nF++IoTw^Xa@xpC>QW~m@rz%0UxAtly9`sfXpHj1uYsui)5jo zm6c@$0b8nUxI_NQ=2i1(4U%(6a_{E3G&y7j4w)%9B+J0{KuZ~BJ0yb^gkCMU6VD{z zP6<>dQr(Ujk|k({#H^YC8OPxX^f)J*0+oz5lYj!{pn(ac_1Iq`6Yva`qkL0V8bC4f z;KZsHx0`5$9FkdDSy@&{z?QKf$3j9RU;qbGXpNee8rV`=H$yhdEyZ@065H4j(Ze1V z-FF=M(K#09X}Dtyu_rbmj)*qIQ4vMlhP#wB+l1SKG>hR5gyfZ+%vjEG@Td?uDiQ&w z3LZFBUlBR7C30k!T8MMM{XE<7?P34xMtBU37VXrDr0JZZ+}^3v9sDQKLE!X_#KBtL zSi)O63BJ7{#dQ?9Xr+#cjYqQ^wdOHr)7Tmb0 z^_<|wjd{es*{s`Kudlv!H*VaxDaX%ijnbXCkZGSY?p2vhHD0`0ePr(uZV{&9#g+!X zIb7ROH`+nymOEQ=dAGa{^zdDYz7rAFcY<~oxWRsBF3FeYE6O|El6ed6H`rTtOGkMfSUlMMj>|Xv5jXuz19t$zkM^^Q))6=S`bN@H-%RtLYqV^;(1rgLAaXASl5rZ0I>hlUqe^zr`MF0Q* diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/mattery_machine_base.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/mattery_machine_base.png deleted file mode 100644 index f6b3c452c2b83a1bbd911bed70e90f4365c252c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10115 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 diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets.png new file mode 100644 index 0000000000000000000000000000000000000000..93c1bb19a76e650a439d3f2662cc1cf4c12e03fc GIT binary patch literal 1812 zcmcgsdsNd$7QVkEBwz?6BJva>?1GhNHS%c11Ok!>xM+ivhfA;)LqvrLngx^mcu03w z1eGHibt{h+6$C+0YFPwUQ7E*eXyqZ0KzT_h5S2t@APxK1p0oe%**j*g55-+%!WH{s{GntWWCX<>fIF^*0@+H8g^P=+s ztVay{j)b_dGmU-&f!}cRXAcH)9`C9897p`NMpl*E^=*Ren~m(Wv~}@BGqL-=4e{49 zGEyyZ?dD`(U)K<;k5m$NSx5ol>9X+TLYl^G@jgHNW33B>Y+DN7vT=e~9i*@f%o__` z=j^n#k#pi>Lcc1*+&p1ne0%ru@O5W*D-vFa8~3k#<)Xr?dMa8Nhu}ZlGL@3Oq_Hm$-Equep-0N&&6%?WY!zA?rTkcZujuY;o??r z4k!9<{0*CswPCD{BxJ4a&2qd&T5Qx_(}O(v*tp~Up9y7m6yIIGEAinX7Bs6dtnHskbi%pT5GLtEeqGhUPN4x5EdOo(pDbwR%Ci zTS8AW{`nSrZl)&NyA%j)ZRq=Q9nQAAZQmOCPhjFcN*BB84SJ zlY(Zi?c%uKE;yJtfm~J~P7bK!}5x;M`n9F@7nMZf;s6{?z=Bzba& zF7c!)V8h5#b__+@eYZ|`rCUDf^sfnQsZ;sp{zUJ`4C#kNEkgD$&<*V}vZ7Qvg5~+@ zg!(H>Zl7To76_RVMcHP%=&xO4$fKlK^6()IDmQ=)#lJ^??*R>59N>{yF8n0{Pj76% zb;h1V6F(*M{s{bSi_Xz!85o8$a?T(ejpQ$*x9^%5N8s9CgrSykc9^zCyEftXzUs1i zeBJvaJ4>ul9}M-tgDE*HFZQS@JTpUkVp}xy{$laj6|-*|X3d~7=hc%{fh=7w`u>w#8}8~7`h={RJHE@e|^=`;(t zQ=_>EJXi49r>nNenL~mOlei)(HyM%jIJBt`uk1EDonHddiY!$5%a&Ct(jvvY#9n&u2y? z{(K{bT^4N9?x2Ao9l?@HQLmzuO-XoE5JYL+@{7@}<$WIQvLJBR=%0jQE?I)10s{`p z9qVvICTKzDsb|^L&0t@p8@o|;D7uM0)1g_f^$vL|5AbhULiYD}5c^FkZQv2LwQKO# zzXZRf$cF_=d6O;1J_Uxmjz!n5r`f^vQ?K~hc;Es0KXFu`0U2z;7)XFKP+}NZKuVGS zCbtiU^!-+cil+6;oz-{xCUcUz22=KFL>Fq60XX$%S?6(rhiB1Dw8Ujz=ah3K? zr)6f^YD8Z*>pqo!1l-WVcnld(031;N-E)BffHA25C!{F*Wd3{4sW%VY5Dy>p;lgpN z_+524sI-MfsKG+7^6VO zP$3V(l$Ad(6F5liA;(^M2Rc+bd7LFV?<& zbv9T3`gPx0aNxt-fhoynKl;8K%l1OlF&{``VH?6-WLB)YT=o0C^5&yd4B;mQVf7*Z cCtLZG9wTsg?L3of|IbxPcF6AF+8}Pu@9K-i{Qv*} literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets.xcf b/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets.xcf index 20f1f2acc3ade6d32c98bdf050019a7fb53c4d60..ee92f6c9d6a5407878703f689b879de507f349ff 100644 GIT binary patch literal 8003 zcmd^DOK)366uwSeyGa|zNem=?q?eb}f`alu3T+l~EFf+xq$(9cqAY4VeyMI8*$%X@ za2H4{?xrg?Y!K=K0iq~73-V=bE zfM_1B$BGwI`RrJ}Qd|T}d;jWawRX9bb*tr4aq(F1(Of=LE|n|pQH{nb`E<%1*MAeo zAWpXsPq_Mz;!D-#RHnF;cPGX{UEW3sF}AW)thvRdOd(sPMLCzNW^1n2_pQxxyE0?; zjlf5S=>FQ^P|e`IKO5ZptHFIQ8$9ru!9%AF9?lqiXxZRxa~M<~fM<9xk*d|QmCJ~F zv6xBKa6CCcwN%zSc8OsKn2$gKp5}V?3T8Ye0Qq#)BWob%8Q=PlZ{6!#yT0{4-+I4q z%`oYoqaVQi7z=}A8kEsLOT+3t$F;%$e%7~+i4NoRjjqppggqMZ)%8OQ8CYF+EkEd} zX#;`jZf6UE&YtN2An4;6IrSg0mBN02fImL@O4CB_vu^6 z=2uFot;20>#mqPM{q7^|AxMGj=l$LeD+9g%Mazuxz1h$A=D#<2QT6|F zTMxX-cM)%^;{aCB0ee|bujF#siknVlF61lam8C@pJFed_>UPVCcD@mL-AC9Hk#dTp zTgbqQyl?qomQ%>vyuIruFMQi3dy~oT>d6b=w8<(ayQ?QJtm=Vp*bw;BcnQ#|A>d#4 zY-ctEzWn*sr`?9I2e!U3_?C~bCn61Du-ZZf)}Uwk^+3W2)kAMSG*F>0LJtWL`_3xB zKj-|01{+%u@!tgr7=kO8cZ;V#|ESY{dPv9lSL6Gcx$JOn8|x znncFujsWdO;%w(eh|I)Ev~wdShNvYZox7pv%rDbv9-qST_zdiU7$y!eesba5!hC%8 z6i{+@_T<9b3(0u=6wv(a7E{Z#3N@iZnO30zH0dQd3p<}PO=(Rqjmo@rZ8VJ+>kO{X zYRzr2=peMYgtQ$sBQxQiO*R9R$mmluMY9>MHn7gl$__jN8Z>j4Sah~=ou<~LisXPp zTwC8z_kUVjyR)G-fGl-iGfCZAU0Vlr%gBJBNlFl88%Cy)vAZMYO|$_ohPkSJ!rb_z z7w&E-*~rSoHD#--43OJ`DFzR+V@O73Lt=oz$7TW2ug2)(ubh* QB`Ey}N`Km{ET_N-0LnEKIRF3v