diff --git a/gradle.properties b/gradle.properties index 011fb69..ccdf0a1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,5 +4,5 @@ org.gradle.jvmargs=-Xmx8G version_minecraft=1.16.4 version_forge_minecraft=1.16.4-35.1.10 version_fml_mappings=20201028-1.16.3 -version_jei=1.16.4:7.6.0.58 -version_engineersdecor=1.1.6-b1 +version_jei=1.16.4:7.6.1.63 +version_engineersdecor=1.1.6-b2 diff --git a/meta/update.json b/meta/update.json index bd8719a..0b6b153 100644 --- a/meta/update.json +++ b/meta/update.json @@ -1,6 +1,7 @@ { "homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/", "1.16.4": { + "1.1.6-b2": "[M] Alternative Clinker Brick recipe (swapped Bricks/Nether Bricks) added.\n[M] Furnace XP handling simplified (simply stores/releases XP for each smelting process).\n[M] Mod devices do not propagate strong Redstone power to adjacent blocks.\n[M] Minor \"librarizing\" changes under the hood.", "1.1.6-b1": "[F] Fixed Metal Crafting Table Hopper access (issue #147, ty umerrr).\n[F] Fixed Dark Shingle Roof Chimney placement restriction (issue #149, thx WenXin20).\n[F] Door tags added for Wood Door and Metal Sliding Door (issue #150, thx WenXin20).\n[A] Electrical Furnace automatically chokes speed and power consumption when the internally stored power is below 20%.", "1.1.5": "[R] Release build v1.1.5.\n[F] Fixed Crafting Table JEI storage slot count.\n[F] Fixed Factory Hopper removed item collection dupe bug (issue #146, thx FatheredPuma81).\n[F] Increased device GUI access ranges beyond the player block selection range.\n[A] Window placement handling improved.\n[M] Steel/Wood Pole and Double-T support placement improved (issue #139, thx Biviho).\n[M] Metal Sliding Door bottom/top shape when opened added.", "1.1.4": "[R] Release build v1.1.4.\n[F] Solar Panel balancing threshold tuned.\n[F] Fixed Catwalk default state (issue #140, thx hvdklauw).\n[M] Updated lang ru_ru file (PR#137, Smollet777).\n[M] Factory Dropper: Added Ignore-External-Redstone mode.", @@ -22,6 +23,6 @@ }, "promos": { "1.16.4-recommended": "1.1.5", - "1.16.4-latest": "1.1.6-b1" + "1.16.4-latest": "1.1.6-b2" } } \ No newline at end of file diff --git a/readme.md b/readme.md index fab6cd0..a0ae565 100644 --- a/readme.md +++ b/readme.md @@ -11,6 +11,11 @@ Mod sources for Minecraft version 1.16.x. ## Version history + - v1.1.6-b2 [M] Alternative Clinker Brick recipe (swapped Bricks/Nether Bricks) added. + [M] Furnace XP handling simplified (simply stores/releases XP for each smelting process). + [M] Mod devices do not propagate strong Redstone power to adjacent blocks. + [M] Minor "librarizing" changes under the hood. + - v1.1.6-b1 [F] Fixed Metal Crafting Table Hopper access (issue #147, ty umerrr). [F] Fixed Dark Shingle Roof Chimney placement restriction (issue #149, thx WenXin20). [F] Door tags added for Wood Door and Metal Sliding Door (issue #150, thx WenXin20). diff --git a/src/main/java/wile/engineersdecor/ModConfig.java b/src/main/java/wile/engineersdecor/ModConfig.java index de9a3a5..75125cd 100644 --- a/src/main/java/wile/engineersdecor/ModConfig.java +++ b/src/main/java/wile/engineersdecor/ModConfig.java @@ -151,9 +151,9 @@ public class ModConfig public final ForgeConfigSpec.IntValue block_breaker_reluctance; public final ForgeConfigSpec.IntValue block_breaker_min_breaking_time; public final ForgeConfigSpec.BooleanValue block_breaker_requires_power; - public final ForgeConfigSpec.IntValue tree_cuttter_energy_consumption; - public final ForgeConfigSpec.IntValue tree_cuttter_cutting_time_needed; - public final ForgeConfigSpec.BooleanValue tree_cuttter_requires_power; + public final ForgeConfigSpec.IntValue tree_cutter_energy_consumption; + public final ForgeConfigSpec.IntValue tree_cutter_cutting_time_needed; + public final ForgeConfigSpec.BooleanValue tree_cutter_requires_power; public final ForgeConfigSpec.IntValue milking_machine_energy_consumption; public final ForgeConfigSpec.IntValue milking_machine_milking_delay; @@ -459,21 +459,21 @@ public class ModConfig .translation(MODID + ".config.block_breaker_requires_power") .comment("Defines if the Small Block Breaker does not work without RF power.") .define("block_breaker_requires_power", false); - tree_cuttter_energy_consumption = builder - .translation(MODID + ".config.tree_cuttter_energy_consumption") + tree_cutter_energy_consumption = builder + .translation(MODID + ".config.tree_cutter_energy_consumption") .comment("Defines how much RF power the Small Tree Cutter requires to magnificently increase the processing speed. " + "The config value can be changed on-the-fly for tuning.") - .defineInRange("tree_cuttter_energy_consumption", EdTreeCutter.TreeCutterTileEntity.DEFAULT_BOOST_ENERGY, 4, 1024); - tree_cuttter_cutting_time_needed = builder - .translation(MODID + ".config.tree_cuttter_cutting_time_needed") + .defineInRange("tree_cutter_energy_consumption", EdTreeCutter.TreeCutterTileEntity.DEFAULT_BOOST_ENERGY, 4, 1024); + tree_cutter_cutting_time_needed = builder + .translation(MODID + ".config.tree_cutter_cutting_time_needed") .comment("Defines how much time the Small Tree Cutter needs to cut a tree without RF power. " + "The value is in seconds. With energy it is 6 times faster. " + "The config value can be changed on-the-fly for tuning.") - .defineInRange("tree_cuttter_cutting_time_needed", EdTreeCutter.TreeCutterTileEntity.DEFAULT_CUTTING_TIME_NEEDED, 10, 240); - tree_cuttter_requires_power = builder - .translation(MODID + ".config.tree_cuttter_requires_power") + .defineInRange("tree_cutter_cutting_time_needed", EdTreeCutter.TreeCutterTileEntity.DEFAULT_CUTTING_TIME_NEEDED, 10, 240); + tree_cutter_requires_power = builder + .translation(MODID + ".config.tree_cutter_requires_power") .comment("Defines if the Small Tree Cutter does not work without RF power.") - .define("tree_cuttter_requires_power", false); + .define("tree_cutter_requires_power", false); milking_machine_energy_consumption = builder .translation(MODID + ".config.milking_machine_energy_consumption") .comment("Defines how much time the Small Milking Machine needs work. " + @@ -671,7 +671,7 @@ public class ModConfig EdElectricalFurnace.ElectricalFurnaceTileEntity.on_config(SERVER.e_furnace_speed_percent.get(), SERVER.e_furnace_power_consumption.get(), SERVER.e_furnace_automatic_pulling.get()); EdSolarPanel.SolarPanelTileEntity.on_config(SERVER.small_solar_panel_peak_production.get()); EdBreaker.BreakerTileEntity.on_config(SERVER.block_breaker_power_consumption.get(), SERVER.block_breaker_reluctance.get(), SERVER.block_breaker_min_breaking_time.get(), SERVER.block_breaker_requires_power.get()); - EdTreeCutter.TreeCutterTileEntity.on_config(SERVER.tree_cuttter_energy_consumption.get(), SERVER.tree_cuttter_cutting_time_needed.get(), SERVER.tree_cuttter_requires_power.get()); + EdTreeCutter.TreeCutterTileEntity.on_config(SERVER.tree_cutter_energy_consumption.get(), SERVER.tree_cutter_cutting_time_needed.get(), SERVER.tree_cutter_requires_power.get()); EdMilker.MilkerTileEntity.on_config(SERVER.milking_machine_energy_consumption.get(), SERVER.milking_machine_milking_delay.get()); EdSlabBlock.on_config(!SERVER.without_direct_slab_pickup.get()); EdSlabSliceBlock.on_config(!SERVER.without_direct_slab_pickup.get()); @@ -683,7 +683,7 @@ public class ModConfig // ----------------------------------------------------------------------------------------------------------------- { // Check if the config is already synchronized or has to be synchronised. - server_config_.putBoolean("tree_cuttter_requires_power", SERVER.tree_cuttter_requires_power.get()); + server_config_.putBoolean("tree_cutter_requires_power", SERVER.tree_cutter_requires_power.get()); server_config_.putBoolean("block_breaker_requires_power", SERVER.block_breaker_requires_power.get()); { String s = String.join(",", optouts_); diff --git a/src/main/java/wile/engineersdecor/blocks/EdBreaker.java b/src/main/java/wile/engineersdecor/blocks/EdBreaker.java index 07751dd..97d8263 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdBreaker.java +++ b/src/main/java/wile/engineersdecor/blocks/EdBreaker.java @@ -42,6 +42,8 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.energy.CapabilityEnergy; import net.minecraftforge.energy.IEnergyStorage; +import wile.engineersdecor.libmc.detail.RfEnergy; + import javax.annotation.Nullable; import java.util.HashSet; import java.util.List; @@ -135,7 +137,7 @@ public class EdBreaker // Tile entity //-------------------------------------------------------------------------------------------------------------------- - public static class BreakerTileEntity extends TileEntity implements ITickableTileEntity, IEnergyStorage + public static class BreakerTileEntity extends TileEntity implements ITickableTileEntity { public static final int IDLE_TICK_INTERVAL = 40; public static final int TICK_INTERVAL = 5; @@ -153,7 +155,8 @@ public class EdBreaker private int active_timer_; private int proc_time_elapsed_; private int time_needed_; - private int energy_; + private final RfEnergy.Battery battery_; + private final LazyOptional energy_handler_; public static void on_config(int boost_energy_per_tick, int breaking_time_per_hardness, int min_breaking_time_ticks, boolean power_required) { @@ -166,19 +169,23 @@ public class EdBreaker } public BreakerTileEntity() - { super(ModContent.TET_SMALL_BLOCK_BREAKER); } + { this(ModContent.TET_SMALL_BLOCK_BREAKER); } public BreakerTileEntity(TileEntityType te_type) - { super(te_type); } + { + super(te_type); + battery_ = new RfEnergy.Battery(energy_max, boost_energy_consumption, 0); + energy_handler_ = battery_.createEnergyHandler(); + } public void block_updated() { if(tick_timer_ > 2) tick_timer_ = 2; } public void readnbt(CompoundNBT nbt) - { energy_ = nbt.getInt("energy"); } + { battery_.load(nbt); } private void writenbt(CompoundNBT nbt) - { nbt.putInt("energy", energy_); } + { battery_.save(nbt); } public void state_message(PlayerEntity player) { @@ -186,8 +193,7 @@ public class EdBreaker if((proc_time_elapsed_ > 0) && (time_needed_ > 0)) { progress = Integer.toString((int)MathHelper.clamp((((double)proc_time_elapsed_) / ((double)time_needed_) * 100), 0, 100)); } - String soc = Integer.toString(MathHelper.clamp((energy_*100/energy_max),0,100)); - Overlay.show(player, Auxiliaries.localizable("block.engineersdecor.small_block_breaker.status", new Object[]{soc, energy_max, progress })); + Overlay.show(player, Auxiliaries.localizable("block.engineersdecor.small_block_breaker.status", new Object[]{battery_.getSOC(), energy_max, progress })); } // TileEntity ------------------------------------------------------------------------------ @@ -207,38 +213,6 @@ public class EdBreaker energy_handler_.invalidate(); } - // IEnergyStorage ---------------------------------------------------------------------------- - - protected LazyOptional energy_handler_ = LazyOptional.of(() -> (IEnergyStorage)this); - - @Override - public boolean canExtract() - { return false; } - - @Override - public boolean canReceive() - { return true; } - - @Override - public int getMaxEnergyStored() - { return boost_energy_consumption*2; } - - @Override - public int getEnergyStored() - { return energy_; } - - @Override - public int extractEnergy(int maxExtract, boolean simulate) - { return 0; } - - @Override - public int receiveEnergy(int maxReceive, boolean simulate) - { - maxReceive = MathHelper.clamp(maxReceive, 0, Math.max(energy_max-energy_, 0)); - if(!simulate) energy_ += maxReceive; - return maxReceive; - } - // Capability export ---------------------------------------------------------------------------- @Override @@ -349,8 +323,7 @@ public class EdBreaker return; } time_needed_ = MathHelper.clamp((int)(target_state.getBlockHardness(world, pos) * breaking_reluctance) + min_breaking_time, min_breaking_time, MAX_BREAKING_TIME); - if(energy_ >= boost_energy_consumption) { - energy_ -= boost_energy_consumption; + if(battery_.draw(boost_energy_consumption)) { proc_time_elapsed_ += TICK_INTERVAL * (1+BOOST_FACTOR); time_needed_ += min_breaking_time * (3*BOOST_FACTOR/5); active_timer_ = 2; diff --git a/src/main/java/wile/engineersdecor/blocks/EdChimneyBlock.java b/src/main/java/wile/engineersdecor/blocks/EdChimneyBlock.java index 6380e09..06f8240 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdChimneyBlock.java +++ b/src/main/java/wile/engineersdecor/blocks/EdChimneyBlock.java @@ -16,10 +16,12 @@ import net.minecraft.state.IntegerProperty; import net.minecraft.state.StateContainer; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.ActionResultType; +import net.minecraft.util.Direction; import net.minecraft.util.Hand; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.world.IWorldReader; import net.minecraft.world.World; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -67,6 +69,10 @@ public class EdChimneyBlock extends DecorBlock.Normal implements IDecorBlock if(p != state.get(POWER)) world.setBlockState(pos, state.with(POWER, p), 2); } + @Override + public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) + { return false; } + @Override @OnlyIn(Dist.CLIENT) public void animateTick(BlockState state, World world, BlockPos pos, Random rnd) diff --git a/src/main/java/wile/engineersdecor/blocks/EdCraftingTable.java b/src/main/java/wile/engineersdecor/blocks/EdCraftingTable.java index fd67e79..967371f 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdCraftingTable.java +++ b/src/main/java/wile/engineersdecor/blocks/EdCraftingTable.java @@ -88,6 +88,10 @@ public class EdCraftingTable public CraftingTableBlock(long config, Block.Properties builder, final AxisAlignedBB[] unrotatedAABBs) { super(config, builder, unrotatedAABBs); } + @Override + public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) + { return false; } + @Override public boolean hasTileEntity(BlockState state) { return true; } @@ -269,8 +273,7 @@ public class EdCraftingTable protected static final String ACTION_DECREASE_CRAFTING_STACKS = "dec-crafting-stacks"; public static final int CRAFTING_SLOTS_BEGIN = 0; - public static final int NUM_OF_CRAFTING_SLOTS = 9; - public static final int STORAGE_SLOTS_BEGIN = NUM_OF_CRAFTING_SLOTS; + public static final int CRAFTING_SLOTS_SIZE = 9; public static final int NUM_OF_STORAGE_SLOTS = CraftingTableTileEntity.NUM_OF_STORAGE_SLOTS; public static final int NUM_OF_STORAGE_ROWS = CraftingTableTileEntity.NUM_OF_STORAGE_ROWS; @@ -307,7 +310,7 @@ public class EdCraftingTable matrix_.openInventory(player_); crafting_result_range_= new InventoryRange(result_, 0, 1, 1); crafting_grid_range_ = new InventoryRange(matrix_, 0, 9, 3); - block_storage_range_ = new InventoryRange(inventory_, STORAGE_SLOTS_BEGIN, NUM_OF_STORAGE_SLOTS, NUM_OF_STORAGE_ROWS); + block_storage_range_ = new InventoryRange(inventory_, CRAFTING_SLOTS_SIZE, NUM_OF_STORAGE_SLOTS, NUM_OF_STORAGE_ROWS); player_storage_range_ = InventoryRange.fromPlayerStorage(player_); player_hotbar_range_ = InventoryRange.fromPlayerHotbar(player_); player_inventory_range_= InventoryRange.fromPlayerInventory(player_); @@ -334,7 +337,7 @@ public class EdCraftingTable for(int x=0; x<9; ++x) { addSlot(new Slot(pinv, x, 8+x*18, 168)); } - // container slotId 46..53 === TE slots 9..17 (storage) + // container slotId 46..63 === TE slots 9..27 (storage) for(int y=0; y<2; ++y) { for(int x=0; x<9; ++x) { addSlot(new Slot(inventory_, 9+x+y*9, 8+x*18, 65+y*18)); @@ -342,7 +345,6 @@ public class EdCraftingTable } if((!player_.world.isRemote) && (inventory_ instanceof CraftingTableTileEntity)) { history_.read(((CraftingTableTileEntity)inventory_).history.copy()); - syncHistory(); } CRAFTING_SLOT_COORDINATES = ImmutableList.copyOf(slotpositions); onCraftMatrixChanged(matrix_); @@ -377,7 +379,7 @@ public class EdCraftingTable } result_.setInventorySlotContents(0, stack); player.connection.sendPacket(new SSetSlotPacket(windowId, 0, stack)); - syncProperties(); + sync(); } catch(Throwable exc) { ModEngineersDecor.logger().error("Recipe failed:", exc); } @@ -411,8 +413,8 @@ public class EdCraftingTable ItemStack slotstack = slot.getStack(); ItemStack stack = slotstack.copy(); if(index == 0) { + if(!this.mergeItemStack(slotstack, 10, 46+NUM_OF_STORAGE_SLOTS, false)) return ItemStack.EMPTY; wpc_.consume((world, pos)->slotstack.getItem().onCreated(slotstack, world, player)); - if(!this.mergeItemStack(slotstack, 10, 46, true)) return ItemStack.EMPTY; slot.onSlotChange(slotstack, stack); } else if(index >= 10 && (index < 46)) { if(!this.mergeItemStack(slotstack, 46, 46+NUM_OF_STORAGE_SLOTS, false)) return ItemStack.EMPTY; @@ -421,18 +423,11 @@ public class EdCraftingTable } else if(!this.mergeItemStack(slotstack, 10, 46, false)) { return ItemStack.EMPTY; } - if(slotstack.isEmpty()) { - slot.putStack(ItemStack.EMPTY); - } else { - slot.onSlotChanged(); - } - if(slotstack.getCount() == stack.getCount()) { - return ItemStack.EMPTY; - } + if(slotstack.isEmpty()) slot.putStack(ItemStack.EMPTY); + slot.onSlotChanged(); + if((index != 0) && (slotstack.getCount() == stack.getCount())) return ItemStack.EMPTY; ItemStack itemstack2 = slot.onTake(player, slotstack); - if(index == 0) { - player.dropItem(itemstack2, false); - } + if(index == 0) player.dropItem(itemstack2, false); return stack; } @@ -466,8 +461,15 @@ public class EdCraftingTable @Override public void onServerPacketReceived(int windowId, CompoundNBT nbt) { - if(nbt.contains("history")) history_.read(nbt.getCompound("history")); - if(nbt.contains("hascollision")) has_recipe_collision_ = nbt.getBoolean("hascollision"); + if(nbt.contains("history")) { + history_.read(nbt.getCompound("history")); + } + if(nbt.contains("hascollision")) { + has_recipe_collision_ = nbt.getBoolean("hascollision"); + } + if(nbt.contains("inventory")) { + Inventories.readNbtStacks(nbt, "inventory", inventory_); + } } @Override @@ -479,22 +481,22 @@ public class EdCraftingTable switch(nbt.getString("action")) { case BUTTON_NEXT: { history_.next(); - syncHistory(); // implicitly clear the grid, so that the player can see the refab, and that no recipe is active. - if(clear_grid_to_storage(player)) changed = true; - if(clear_grid_to_player(player)) { changed = true; player_inventory_changed = true; } + if(crafting_grid_range_.move(block_storage_range_)) changed = true; + if(crafting_grid_range_.move(player_inventory_range_)) { changed = true; player_inventory_changed = true; } + sync(); } break; case BUTTON_PREV: { history_.prev(); - syncHistory(); - if(clear_grid_to_storage(player)) changed = true; - if(clear_grid_to_player(player)) { changed = true; player_inventory_changed = true; } + if(crafting_grid_range_.move(block_storage_range_)) changed = true; + if(crafting_grid_range_.move(player_inventory_range_)) { changed = true; player_inventory_changed = true; } + sync(); } break; case BUTTON_CLEAR_GRID: { history_.reset_selection(); - syncHistory(); - if(clear_grid_to_storage(player)) changed = true; - if(clear_grid_to_player(player)) { changed = true; player_inventory_changed = true; } + sync(); + if(crafting_grid_range_.move(block_storage_range_)) changed = true; + if(crafting_grid_range_.move(player_inventory_range_)) { changed = true; player_inventory_changed = true; } } break; case ACTION_PLACE_CURRENT_HISTORY_SEL: { if(place_stacks( @@ -550,8 +552,12 @@ public class EdCraftingTable } else if(container_slot_id < 10) { // from crafting grid to player inventory, we clear the grid here as this is most likely // what is wanted in the end. Saves clicking the other grid stacks. - if(clear_grid_to_storage(player)) changed = true; - if(clear_grid_to_player(player)) { changed = true; player_inventory_changed = true; } + if(crafting_grid_range_.move(player_inventory_range_, true)) { + crafting_grid_range_.move(player_inventory_range_, false, false, true); + changed = true; player_inventory_changed = true; + } + if(crafting_grid_range_.move(block_storage_range_)) changed = true; + if(crafting_grid_range_.move(player_inventory_range_, true)) { changed = true; player_inventory_changed = true; } break; } IInventory from_inventory; @@ -560,7 +566,7 @@ public class EdCraftingTable if(container_slot_id >= 46) { // from storage to player inventory from_inventory = inventory_; - from_slot = container_slot_id - 46 + STORAGE_SLOTS_BEGIN; + from_slot = container_slot_id - 46 + CRAFTING_SLOTS_SIZE; to_ranges = new InventoryRange[] {player_storage_range_, player_hotbar_range_}; } else { // from player to storage (otherwise ACTION_PLACE_SHIFTCLICKED_STACK would have been used) @@ -606,32 +612,24 @@ public class EdCraftingTable public CraftingHistory history() { return history_; } - private void syncHistory() + private void sync() { if(!with_assist) return; this.wpc_.consume((world,pos)->{ if(world.isRemote()) return; CompoundNBT hist_nbt = history_.write(); + final CompoundNBT nbt = new CompoundNBT(); if((inventory_ instanceof CraftingTableTileEntity)) { ((CraftingTableTileEntity)inventory_).history = hist_nbt.copy(); inventory_.markDirty(); + nbt.put("inventory", ((CraftingTableTileEntity)inventory_).mainInventory().save(false)); } - final CompoundNBT nbt = new CompoundNBT(); nbt.put("history", hist_nbt); nbt.putBoolean("hascollision", has_recipe_collision_); Networking.PacketContainerSyncServerToClient.sendToListeners(world, this, nbt); }); } - private void syncProperties() - { - this.wpc_.consume((world,pos)->{ - final CompoundNBT nbt = new CompoundNBT(); - nbt.putBoolean("hascollision", has_recipe_collision_); - Networking.PacketContainerSyncServerToClient.sendToListeners(world, this, nbt); - }); - } - // private aux methods --------------------------------------------------------------------- public boolean has_recipe_collision() @@ -772,7 +770,6 @@ public class EdCraftingTable } if(recipe != null) { onCraftMatrixChanged(inventory_); - syncHistory(); } } @@ -850,12 +847,6 @@ public class EdCraftingTable return stacks; } - private boolean clear_grid_to_storage(PlayerEntity player) - { return crafting_grid_range_.move(block_storage_range_); } - - private boolean clear_grid_to_player(PlayerEntity player) - { return crafting_grid_range_.move(player_inventory_range_); } - private PlacementResult place_stacks(final InventoryRange[] ranges, final List to_fill) { if(history_.current_recipe() != null) result_.setRecipeUsed(history_.current_recipe()); @@ -1168,7 +1159,7 @@ public class EdCraftingTable palce_in_crafting_grid = (!history.isEmpty()); if(!palce_in_crafting_grid) { for(int i = 0; i < 9; ++i) { - if(!(getContainer().getSlot(i).getStack().isEmpty())) { + if(!Inventories.areItemStacksDifferent(getContainer().getSlot(i).getStack(), slot.getStack())) { palce_in_crafting_grid = true; break; } @@ -1190,7 +1181,7 @@ public class EdCraftingTable action(CraftingTableContainer.ACTION_MOVE_ALL_STACKS, nbt); return; } else if((slotId > 0) && (slotId <= 9)) { - // Move from grid to storage or player inventory + // Move from crafting grid to inventory CompoundNBT nbt = new CompoundNBT(); nbt.putInt("containerslot", slotId); action(CraftingTableContainer.ACTION_MOVE_STACK, nbt); @@ -1471,7 +1462,7 @@ public class EdCraftingTable @Override protected void onCrafting(ItemStack stack) { - if((with_assist) && ((player.world!=null) && (!(player.world.isRemote))) && (!stack.isEmpty())) { + if((with_assist) && ((player.world!=null) && (!(player.world.isRemote()))) && (!stack.isEmpty())) { final IRecipe recipe = ((CraftResultInventory)this.inventory).getRecipeUsed(); final ArrayList grid = new ArrayList(); grid.add(stack); @@ -1479,10 +1470,10 @@ public class EdCraftingTable if(recipe instanceof ICraftingRecipe) { container.history().add(grid, (ICraftingRecipe)recipe); container.history().reset_current(); - container.syncHistory(); } } super.onCrafting(stack); + container.sync(); } } diff --git a/src/main/java/wile/engineersdecor/blocks/EdDropper.java b/src/main/java/wile/engineersdecor/blocks/EdDropper.java index f4e9e55..43ffee7 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdDropper.java +++ b/src/main/java/wile/engineersdecor/blocks/EdDropper.java @@ -11,6 +11,7 @@ package wile.engineersdecor.blocks; import net.minecraft.inventory.container.ClickType; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.IBlockReader; +import net.minecraft.world.IWorldReader; import net.minecraft.world.World; import net.minecraft.state.BooleanProperty; import net.minecraft.state.StateContainer; @@ -45,17 +46,18 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.wrapper.SidedInvWrapper; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.matrix.MatrixStack; +import net.minecraftforge.items.wrapper.InvWrapper; import wile.engineersdecor.ModContent; import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.libmc.client.ContainerGui; import wile.engineersdecor.libmc.detail.Auxiliaries; import wile.engineersdecor.libmc.detail.Inventories; import wile.engineersdecor.libmc.detail.Inventories.InventoryRange; +import wile.engineersdecor.libmc.detail.Inventories.StorageInventory; import wile.engineersdecor.libmc.detail.Networking; import wile.engineersdecor.libmc.detail.TooltipDisplay; import wile.engineersdecor.libmc.detail.TooltipDisplay.TipRange; @@ -158,7 +160,7 @@ public class EdDropper } stacks.add(stack); } else { - for(ItemStack stack: ((DropperTileEntity)te).stacks_) { + for(ItemStack stack: ((DropperTileEntity)te).main_inventory_) { if(!stack.isEmpty()) stacks.add(stack); } ((DropperTileEntity)te).reset_rtstate(); @@ -188,26 +190,15 @@ public class EdDropper } @Override - @SuppressWarnings("deprecation") - public boolean canProvidePower(BlockState state) - { return true; } - - @Override - @SuppressWarnings("deprecation") - public int getWeakPower(BlockState blockState, IBlockReader blockAccess, BlockPos pos, Direction side) - { return 0; } - - @Override - @SuppressWarnings("deprecation") - public int getStrongPower(BlockState blockState, IBlockReader blockAccess, BlockPos pos, Direction side) - { return 0; } + public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) + { return false; } } //-------------------------------------------------------------------------------------------------------------------- // Tile entity //-------------------------------------------------------------------------------------------------------------------- - public static class DropperTileEntity extends TileEntity implements ITickableTileEntity, INameable, IInventory, INamedContainerProvider, ISidedInventory + public static class DropperTileEntity extends TileEntity implements ITickableTileEntity, INameable, INamedContainerProvider { public static final int NUM_OF_FIELDS = 16; public static final int TICK_INTERVAL = 32; @@ -242,9 +233,9 @@ public class EdDropper private int drop_period_ = 0; private int drop_slot_index_ = 0; private int tick_timer_ = 0; - protected NonNullList stacks_; - protected final InventoryRange storage_slot_range_; - protected final InventoryRange filter_slot_range_; + protected final Inventories.StorageInventory main_inventory_ = new StorageInventory(this, NUM_OF_SLOTS, 1); + protected final InventoryRange storage_slot_range_ = new InventoryRange(main_inventory_, INPUT_SLOTS_FIRST, INPUT_SLOTS_SIZE); + protected final InventoryRange filter_slot_range_ = new InventoryRange(main_inventory_, CTRL_SLOTS_FIRST, CTRL_SLOTS_SIZE); public static void on_config(int cooldown_ticks) { @@ -255,19 +246,13 @@ public class EdDropper { this(ModContent.TET_FACTORY_DROPPER); } public DropperTileEntity(TileEntityType te_type) - { - super(te_type); - stacks_ = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); - storage_slot_range_ = new InventoryRange(this, INPUT_SLOTS_FIRST, INPUT_SLOTS_SIZE); - filter_slot_range_ = new InventoryRange(this, CTRL_SLOTS_FIRST, CTRL_SLOTS_SIZE); - reset_rtstate(); - } + { super(te_type); reset_rtstate(); } public CompoundNBT clear_getnbt() { CompoundNBT nbt = new CompoundNBT(); writenbt(nbt, false); - for(int i=0; iwithSize(NUM_OF_SLOTS, ItemStack.EMPTY); - ItemStackHelper.loadAllItems(nbt, stacks_); - while(stacks_.size() < NUM_OF_SLOTS) stacks_.add(ItemStack.EMPTY); + main_inventory_.load(nbt); block_power_signal_ = nbt.getBoolean("powered"); open_timer_ = nbt.getInt("open_timer"); drop_speed_ = nbt.getInt("drop_speed"); @@ -300,7 +283,7 @@ public class EdDropper protected void writenbt(CompoundNBT nbt, boolean update_packet) { - ItemStackHelper.saveAllItems(nbt, stacks_); + main_inventory_.save(nbt); nbt.putBoolean("powered", block_power_signal_); nbt.putInt("open_timer", open_timer_); nbt.putInt("drop_speed", drop_speed_); @@ -339,7 +322,7 @@ public class EdDropper public void remove() { super.remove(); - Arrays.stream(item_handlers).forEach(LazyOptional::invalidate); + item_handler_.invalidate(); } // INamable ---------------------------------------------------------------------------------------------- @@ -364,66 +347,7 @@ public class EdDropper @Override public Container createMenu(int id, PlayerInventory inventory, PlayerEntity player ) - { return new DropperContainer(id, inventory, this, IWorldPosCallable.of(world, pos), fields); } - - // IInventory ------------------------------------------------------------------------------------------- - - @Override - public int getSizeInventory() - { return stacks_.size(); } - - @Override - public boolean isEmpty() - { for(ItemStack stack: stacks_) { if(!stack.isEmpty()) return false; } return true; } - - @Override - public ItemStack getStackInSlot(int index) - { return (index < getSizeInventory()) ? stacks_.get(index) : ItemStack.EMPTY; } - - @Override - public ItemStack decrStackSize(int index, int count) - { return ItemStackHelper.getAndSplit(stacks_, index, count); } - - @Override - public ItemStack removeStackFromSlot(int index) - { return ItemStackHelper.getAndRemove(stacks_, index); } - - @Override - public void setInventorySlotContents(int index, ItemStack stack) - { - stacks_.set(index, stack); - if(stack.getCount() > getInventoryStackLimit()) stack.setCount(getInventoryStackLimit()); - if(tick_timer_ > 8) tick_timer_ = 8; - markDirty(); - } - - @Override - public int getInventoryStackLimit() - { return 64; } - - @Override - public void markDirty() - { super.markDirty(); } - - @Override - public boolean isUsableByPlayer(PlayerEntity player) - { return ((getWorld().getTileEntity(getPos()) == this)) && (getPos().distanceSq(player.getPosition()) < 64); } - - @Override - public void openInventory(PlayerEntity player) - {} - - @Override - public void closeInventory(PlayerEntity player) - { markDirty(); } - - @Override - public boolean isItemValidForSlot(int index, ItemStack stack) - { return true; } - - @Override - public void clear() - { stacks_.clear(); } + { return new DropperContainer(id, inventory, main_inventory_, IWorldPosCallable.of(world, pos), fields); } // Fields ----------------------------------------------------------------------------------------------- @@ -473,33 +397,14 @@ public class EdDropper } }; - // ISidedInventory -------------------------------------------------------------------------------------- - - LazyOptional[] item_handlers = SidedInvWrapper.create(this, Direction.UP); - private static final int[] SIDED_INV_SLOTS; - static { - SIDED_INV_SLOTS = new int[INPUT_SLOTS_SIZE]; - for(int i=0; i item_handler_ = LazyOptional.of(()->new InvWrapper(storage_slot_range_)); + @Override public LazyOptional getCapability(net.minecraftforge.common.capabilities.Capability capability, @Nullable Direction facing) { - if(capability==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return item_handlers[0].cast(); + if(capability==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return item_handler_.cast(); return super.getCapability(capability, facing); } @@ -613,7 +518,7 @@ public class EdDropper int last_filter_matches_[] = filter_matches_.clone(); for(int ci=0; ci= INPUT_SLOTS_SIZE) drop_slot_index_ = 0; final int ic = drop_slot_index_; drop_slot_index_ = next_slot(drop_slot_index_); - ItemStack ds = stacks_.get(ic); + ItemStack ds = main_inventory_.getStackInSlot(ic); if((!ds.isEmpty()) && (ds.getCount() >= drop_count_)) { boolean skip_stack = false; for(int ci = 0; (ci 1) { - drop_stacks[fi] = stacks_.get(CTRL_SLOTS_FIRST+fi).copy(); + drop_stacks[fi] = main_inventory_.getStackInSlot(CTRL_SLOTS_FIRST+fi).copy(); int ntoremove = drop_stacks[fi].getCount(); for(int i=INPUT_SLOTS_SIZE-1; (i>=0) && (ntoremove>0); --i) { - ItemStack stack = stacks_.get(i); + ItemStack stack = main_inventory_.getStackInSlot(i); if(Inventories.areItemStacksDifferent(stack, drop_stacks[fi])) continue; if(stack.getCount() <= ntoremove) { ntoremove -= stack.getCount(); - stacks_.set(i, ItemStack.EMPTY); + main_inventory_.setInventorySlotContents(i, ItemStack.EMPTY); } else { stack.shrink(ntoremove); ntoremove = 0; - stacks_.set(i, stack); + main_inventory_.setInventorySlotContents(i, stack); } } if(ntoremove > 0) drop_stacks[fi].shrink(ntoremove); @@ -727,7 +632,7 @@ public class EdDropper { boolean found = false; for(int i = 0; i < storage_slot_range_.size; ++i) { - if(!stacks_.get(drop_slot_index_).isEmpty()) { found=true; break; } + if(!main_inventory_.getStackInSlot(drop_slot_index_).isEmpty()) { found=true; break; } drop_slot_index_ = next_slot(drop_slot_index_); } if(!found) drop_slot_index_ = 0; @@ -850,7 +755,7 @@ public class EdDropper @Override public void onClientPacketReceived(int windowId, PlayerEntity player, CompoundNBT nbt) { - if(!(inventory_ instanceof DropperTileEntity)) return; + if((!(inventory_ instanceof StorageInventory)) || (!(((StorageInventory)inventory_).getTileEntity() instanceof DropperTileEntity))) return; if(nbt.contains("action")) { boolean changed = false; final int slotId = nbt.contains("slot") ? nbt.getInt("slot") : -1; @@ -869,7 +774,7 @@ public class EdDropper detectAndSendChanges(); } } else { - DropperTileEntity te = (DropperTileEntity)inventory_; + DropperTileEntity te = (DropperTileEntity)((StorageInventory)inventory_).getTileEntity(); if(nbt.contains("drop_speed")) te.drop_speed_ = MathHelper.clamp(nbt.getInt("drop_speed"), 0, 100); if(nbt.contains("drop_xdev")) te.drop_xdev_ = MathHelper.clamp(nbt.getInt("drop_xdev"), -100, 100); if(nbt.contains("drop_ydev")) te.drop_ydev_ = MathHelper.clamp(nbt.getInt("drop_ydev"), -100, 100); diff --git a/src/main/java/wile/engineersdecor/blocks/EdElectricalFurnace.java b/src/main/java/wile/engineersdecor/blocks/EdElectricalFurnace.java index 7ea3630..17f910e 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdElectricalFurnace.java +++ b/src/main/java/wile/engineersdecor/blocks/EdElectricalFurnace.java @@ -9,6 +9,7 @@ package wile.engineersdecor.blocks; import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; @@ -20,7 +21,6 @@ import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.tileentity.TileEntityType; import net.minecraft.item.*; import net.minecraft.item.crafting.AbstractCookingRecipe; -import net.minecraft.item.crafting.FurnaceRecipe; import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.IRecipeType; import net.minecraft.entity.player.PlayerEntity; @@ -44,20 +44,20 @@ import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.fml.network.NetworkHooks; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.energy.CapabilityEnergy; -import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; -import com.mojang.blaze3d.systems.RenderSystem; import wile.engineersdecor.ModContent; import wile.engineersdecor.ModEngineersDecor; +import wile.engineersdecor.blocks.EdFurnace.FurnaceTileEntity; +import wile.engineersdecor.libmc.detail.Inventories.StorageInventory; +import wile.engineersdecor.libmc.detail.Inventories.MappedItemHandler; import wile.engineersdecor.libmc.detail.TooltipDisplay; import wile.engineersdecor.libmc.detail.TooltipDisplay.TipRange; import wile.engineersdecor.libmc.client.ContainerGui; import wile.engineersdecor.libmc.detail.Inventories; import wile.engineersdecor.libmc.detail.Networking; -import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Arrays; import java.util.Random; @@ -116,28 +116,29 @@ public class EdElectricalFurnace // Tile entity //-------------------------------------------------------------------------------------------------------------------- - public static class ElectricalFurnaceTileEntity extends EdFurnace.FurnaceTileEntity implements ITickableTileEntity, INameable, IInventory, INamedContainerProvider, ISidedInventory, IEnergyStorage + public static class ElectricalFurnaceTileEntity extends EdFurnace.FurnaceTileEntity implements ITickableTileEntity, INameable, INamedContainerProvider { - public static final IRecipeType RECIPE_TYPE = IRecipeType.SMELTING; - public static final int NUM_OF_FIELDS = 7; - public static final int TICK_INTERVAL = 4; - public static final int FIFO_INTERVAL = 20; - public static final int HEAT_CAPACITY = 200; - public static final int HEAT_INCREMENT = 20; - public static final int MAX_ENERGY_TRANSFER = 1024; - public static final int MAX_ENERGY_BUFFER = 32000; - public static final int MAX_SPEED_SETTING = 3; - public static final int NUM_OF_SLOTS = 7; - public static final int SMELTING_INPUT_SLOT_NO = 0; - public static final int SMELTING_AUX_SLOT_NO = 1; - public static final int SMELTING_OUTPUT_SLOT_NO = 2; - public static final int FIFO_INPUT_0_SLOT_NO = 3; - public static final int FIFO_INPUT_1_SLOT_NO = 4; - public static final int FIFO_OUTPUT_0_SLOT_NO = 5; - public static final int FIFO_OUTPUT_1_SLOT_NO = 6; - public static final int DEFAULT_SPEED_PERCENT = 250; - public static final int DEFAULT_ENERGY_CONSUMPTION = 16; - public static final int DEFAULT_SCALED_ENERGY_CONSUMPTION = DEFAULT_ENERGY_CONSUMPTION * HEAT_INCREMENT * DEFAULT_SPEED_PERCENT / 100; + private static final int NUM_OF_FIELDS = 7; + private static final int TICK_INTERVAL = 4; + private static final int FIFO_INTERVAL = 20; + private static final int HEAT_CAPACITY = 200; + private static final int HEAT_INCREMENT = 20; + private static final int MAX_BURNTIME = 0x7fff; + private static final int MAX_XP_STORED = 65535; + private static final int MAX_ENERGY_TRANSFER = 1024; + private static final int MAX_ENERGY_BUFFER = 32000; + private static final int MAX_SPEED_SETTING = 3; + private static final int NUM_OF_SLOTS = 7; + private static final int SMELTING_INPUT_SLOT_NO = 0; + private static final int SMELTING_AUX_SLOT_NO = 1; + private static final int SMELTING_OUTPUT_SLOT_NO = 2; + private static final int FIFO_INPUT_0_SLOT_NO = 3; + private static final int FIFO_INPUT_1_SLOT_NO = 4; + private static final int FIFO_OUTPUT_0_SLOT_NO = 5; + private static final int FIFO_OUTPUT_1_SLOT_NO = 6; + public static final int DEFAULT_SPEED_PERCENT = 290; + public static final int DEFAULT_ENERGY_CONSUMPTION = 16; + public static final int DEFAULT_SCALED_ENERGY_CONSUMPTION = DEFAULT_ENERGY_CONSUMPTION * HEAT_INCREMENT * DEFAULT_SPEED_PERCENT / 100; // Config ---------------------------------------------------------------------------------- @@ -158,66 +159,78 @@ public class EdElectricalFurnace // ElectricalFurnaceTileEntity ----------------------------------------------------------------------------- - private int burntime_left_ = 0; - private int proc_time_elapsed_ = 0; - private int proc_time_needed_ = 0; - private int energy_stored_ = 0; - private int field_max_energy_stored_ = 0; - private int field_isburning_ = 0; private int speed_ = 1; - private int tick_timer_ = 0; - private int fifo_timer_ = 0; private boolean enabled_ = false; + private final LazyOptional item_handler_; public ElectricalFurnaceTileEntity() { this(ModContent.TET_SMALL_ELECTRICAL_FURNACE); } public ElectricalFurnaceTileEntity(TileEntityType te_type) - { super(te_type); } + { + super(te_type, NUM_OF_SLOTS); + battery_.setMaxEnergyStored(MAX_ENERGY_BUFFER); + battery_.setChargeRate(MAX_ENERGY_TRANSFER); + battery_.setDischargeRate(0); + inventory_.setValidator((index, stack)->{ + switch(index) { + case SMELTING_INPUT_SLOT_NO: + case FIFO_INPUT_0_SLOT_NO: + case FIFO_INPUT_1_SLOT_NO: + return true; + default: + return false; + } + }); + item_handler_ = MappedItemHandler.createGenericHandler(inventory_, + (slot,stack)->((slot==FIFO_OUTPUT_0_SLOT_NO) || (slot==FIFO_OUTPUT_1_SLOT_NO)), + (slot,stack)->((slot==FIFO_INPUT_0_SLOT_NO) || (slot==FIFO_INPUT_1_SLOT_NO)), + Arrays.asList(FIFO_OUTPUT_0_SLOT_NO,FIFO_OUTPUT_1_SLOT_NO,FIFO_INPUT_0_SLOT_NO,FIFO_INPUT_1_SLOT_NO) + ); + } public void reset() { - super.reset(); - stacks_ = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); + inventory_.clear(); burntime_left_ = 0; proc_time_elapsed_ = 0; proc_time_needed_ = 0; fifo_timer_ = 0; tick_timer_ = 0; - energy_stored_ = 0; + battery_.clear(); speed_ = 1; - field_max_energy_stored_ = getMaxEnergyStored(); - field_isburning_ = 0; + field_is_burning_ = 0; } public void readnbt(CompoundNBT nbt) { - ItemStackHelper.loadAllItems(nbt, this.stacks_); - while(this.stacks_.size() < NUM_OF_SLOTS) this.stacks_.add(ItemStack.EMPTY); burntime_left_ = nbt.getInt("BurnTime"); proc_time_elapsed_ = nbt.getInt("CookTime"); proc_time_needed_ = nbt.getInt("CookTimeTotal"); - energy_stored_ = nbt.getInt("Energy"); + xp_stored_ = nbt.getFloat("XpStored"); speed_ = nbt.getInt("SpeedSetting"); speed_ = (speed_ < 0) ? (1) : ((speed_>MAX_SPEED_SETTING) ? MAX_SPEED_SETTING : speed_); + battery_.load(nbt, "Energy"); + inventory_.load(nbt); } protected void writenbt(CompoundNBT nbt) { nbt.putInt("BurnTime", MathHelper.clamp(burntime_left_, 0, HEAT_CAPACITY)); - nbt.putInt("CookTime", MathHelper.clamp(proc_time_elapsed_, 0, MAX_BURNTIME)); + nbt.putInt("CookTime", MathHelper.clamp((int)proc_time_elapsed_, 0, MAX_BURNTIME)); nbt.putInt("CookTimeTotal", MathHelper.clamp(proc_time_needed_, 0, MAX_BURNTIME)); - nbt.putInt("Energy", MathHelper.clamp(energy_stored_, 0, MAX_ENERGY_BUFFER)); nbt.putInt("SpeedSetting", MathHelper.clamp(speed_, -1, MAX_SPEED_SETTING)); - ItemStackHelper.saveAllItems(nbt, stacks_); + nbt.putFloat("XpStored", MathHelper.clamp(xp_stored_, 0, MAX_XP_STORED)); + battery_.save(nbt, "Energy"); + inventory_.save(nbt); } public int getComparatorOutput() { - return (energy_stored_ <= 0) ? (0) : ( - (stacks_.get(FIFO_INPUT_1_SLOT_NO).isEmpty() ? 0 : 5) + - (stacks_.get(FIFO_INPUT_0_SLOT_NO).isEmpty() ? 0 : 5) + - (stacks_.get(SMELTING_INPUT_SLOT_NO).isEmpty() ? 0 : 5) + return (battery_.isEmpty()) ? (0) : ( + (inventory_.getStackInSlot(FIFO_INPUT_1_SLOT_NO).isEmpty() ? 0 : 5) + + (inventory_.getStackInSlot(FIFO_INPUT_0_SLOT_NO).isEmpty() ? 0 : 5) + + (inventory_.getStackInSlot(SMELTING_INPUT_SLOT_NO).isEmpty() ? 0 : 5) ); } @@ -235,7 +248,6 @@ public class EdElectricalFurnace public void remove() { super.remove(); - Arrays.stream(item_handlers).forEach(LazyOptional::invalidate); item_handler_.invalidate(); energy_handler_.invalidate(); } @@ -250,26 +262,7 @@ public class EdElectricalFurnace @Override public Container createMenu(int id, PlayerInventory inventory, PlayerEntity player ) - { return new EdElectricalFurnace.ElectricalFurnaceContainer(id, inventory, this, IWorldPosCallable.of(world, pos), fields); } - - // IInventory ------------------------------------------------------------------------------ - - @Override - public boolean isItemValidForSlot(int index, ItemStack stack) - { - switch(index) { - case SMELTING_INPUT_SLOT_NO: - case FIFO_INPUT_0_SLOT_NO: - case FIFO_INPUT_1_SLOT_NO: - return true; - default: - return false; - } - } - - @Override - public ItemStack getStackInSlot(int index) - { return ((index < 0) || (index >= SIDED_INV_SLOTS.length)) ? ItemStack.EMPTY : stacks_.get(SIDED_INV_SLOTS[index]); } + { return new EdElectricalFurnace.ElectricalFurnaceContainer(id, inventory, inventory_, IWorldPosCallable.of(world, pos), fields); } // Fields ----------------------------------------------------------------------------------------------- @@ -280,12 +273,12 @@ public class EdElectricalFurnace { switch(id) { case 0: return ElectricalFurnaceTileEntity.this.burntime_left_; - case 1: return ElectricalFurnaceTileEntity.this.energy_stored_; - case 2: return ElectricalFurnaceTileEntity.this.proc_time_elapsed_; + case 1: return ElectricalFurnaceTileEntity.this.battery_.getEnergyStored(); + case 2: return (int)ElectricalFurnaceTileEntity.this.proc_time_elapsed_; case 3: return ElectricalFurnaceTileEntity.this.proc_time_needed_; case 4: return ElectricalFurnaceTileEntity.this.speed_; - case 5: return ElectricalFurnaceTileEntity.this.field_max_energy_stored_; - case 6: return ElectricalFurnaceTileEntity.this.field_isburning_; + case 5: return ElectricalFurnaceTileEntity.this.battery_.getMaxEnergyStored(); + case 6: return ElectricalFurnaceTileEntity.this.field_is_burning_; default: return 0; } } @@ -294,172 +287,18 @@ public class EdElectricalFurnace { switch(id) { case 0: ElectricalFurnaceTileEntity.this.burntime_left_ = value; break; - case 1: ElectricalFurnaceTileEntity.this.energy_stored_ = value; break; + case 1: ElectricalFurnaceTileEntity.this.battery_.setEnergyStored(value); break; case 2: ElectricalFurnaceTileEntity.this.proc_time_elapsed_ = value; break; case 3: ElectricalFurnaceTileEntity.this.proc_time_needed_ = value; break; case 4: ElectricalFurnaceTileEntity.this.speed_ = value; break; - case 5: ElectricalFurnaceTileEntity.this.field_max_energy_stored_ = value; break; - case 6: ElectricalFurnaceTileEntity.this.field_isburning_ = value; break; + case 5: ElectricalFurnaceTileEntity.this.battery_.setMaxEnergyStored(value); break; + case 6: ElectricalFurnaceTileEntity.this.field_is_burning_ = value; break; } } }; - // ISidedInventory ---------------------------------------------------------------------------- - - private static final int[] SIDED_INV_SLOTS = new int[] { - SMELTING_INPUT_SLOT_NO, SMELTING_AUX_SLOT_NO, SMELTING_OUTPUT_SLOT_NO, - FIFO_INPUT_0_SLOT_NO, FIFO_INPUT_1_SLOT_NO, FIFO_OUTPUT_0_SLOT_NO, FIFO_OUTPUT_1_SLOT_NO - }; - - @Override - public int[] getSlotsForFace(Direction side) - { return SIDED_INV_SLOTS; } - - @Override - public boolean canInsertItem(int index, ItemStack itemStackIn, Direction direction) - { return ((index==FIFO_INPUT_0_SLOT_NO) || (index==FIFO_INPUT_1_SLOT_NO)) && isItemValidForSlot(index, itemStackIn); } - - @Override - public boolean canExtractItem(int index, ItemStack stack, Direction direction) - { return (index==FIFO_OUTPUT_0_SLOT_NO) || (index==FIFO_OUTPUT_1_SLOT_NO); } - - // IEnergyStorage ---------------------------------------------------------------------------- - - @Override - public boolean canExtract() - { return false; } - - @Override - public boolean canReceive() - { return true; } - - @Override - public int getMaxEnergyStored() - { return MAX_ENERGY_BUFFER; } - - @Override - public int getEnergyStored() - { return energy_stored_; } - - @Override - public int extractEnergy(int maxExtract, boolean simulate) - { return 0; } - - @Override - public int receiveEnergy(int maxReceive, boolean simulate) - { - if(energy_stored_ >= MAX_ENERGY_BUFFER) return 0; - int n = Math.min(maxReceive, (MAX_ENERGY_BUFFER - energy_stored_)); - if(n > MAX_ENERGY_TRANSFER) n = MAX_ENERGY_TRANSFER; - if(!simulate) {energy_stored_ += n; markDirty(); } - return n; - } - - // IItemHandler -------------------------------------------------------------------------------- - - protected static class BItemHandler implements IItemHandler - { - private ElectricalFurnaceTileEntity te; - - BItemHandler(ElectricalFurnaceTileEntity te) - { this.te = te; } - - @Override - public int getSlots() - { return SIDED_INV_SLOTS.length; } - - @Override - @Nonnull - public ItemStack getStackInSlot(int index) - { return te.getStackInSlot(index); } - - @Override - public int getSlotLimit(int index) - { return te.getInventoryStackLimit(); } - - @Override - public boolean isItemValid(int slot, @Nonnull ItemStack stack) - { return true; } - - @Override - @Nonnull - public ItemStack insertItem(int index, @Nonnull ItemStack stack, boolean simulate) - { - if(stack.isEmpty()) return ItemStack.EMPTY; - if((index < 0) || (index >= SIDED_INV_SLOTS.length)) return ItemStack.EMPTY; - int slotno = SIDED_INV_SLOTS[index]; - ItemStack slotstack = getStackInSlot(slotno); - if(!slotstack.isEmpty()) { - if(slotstack.getCount() >= Math.min(slotstack.getMaxStackSize(), getSlotLimit(index))) return stack; - if(!ItemHandlerHelper.canItemStacksStack(stack, slotstack)) return stack; - if(!te.canInsertItem(slotno, stack, Direction.UP) || (!te.isItemValidForSlot(slotno, stack))) return stack; - int n = Math.min(stack.getMaxStackSize(), getSlotLimit(index)) - slotstack.getCount(); - if(stack.getCount() <= n) { - if(!simulate) { - ItemStack copy = stack.copy(); - copy.grow(slotstack.getCount()); - te.setInventorySlotContents(slotno, copy); - } - return ItemStack.EMPTY; - } else { - stack = stack.copy(); - if(!simulate) { - ItemStack copy = stack.split(n); - copy.grow(slotstack.getCount()); - te.setInventorySlotContents(slotno, copy); - return stack; - } else { - stack.shrink(n); - return stack; - } - } - } else { - if(!te.canInsertItem(slotno, stack, Direction.UP) || (!te.isItemValidForSlot(slotno, stack))) return stack; - int n = Math.min(stack.getMaxStackSize(), getSlotLimit(index)); - if(n < stack.getCount()) { - stack = stack.copy(); - if(!simulate) { - te.setInventorySlotContents(slotno, stack.split(n)); - return stack; - } else { - stack.shrink(n); - return stack; - } - } else { - if(!simulate) te.setInventorySlotContents(slotno, stack); - return ItemStack.EMPTY; - } - } - } - - @Override - @Nonnull - public ItemStack extractItem(int index, int amount, boolean simulate) - { - if(amount == 0) return ItemStack.EMPTY; - if((index < 0) || (index >= SIDED_INV_SLOTS.length)) return ItemStack.EMPTY; - int slotno = SIDED_INV_SLOTS[index]; - ItemStack stackInSlot = getStackInSlot(slotno); - if(stackInSlot.isEmpty()) return ItemStack.EMPTY; - if(!te.canExtractItem(slotno, stackInSlot, Direction.DOWN)) return ItemStack.EMPTY; - if(simulate) { - if(stackInSlot.getCount() < amount) return stackInSlot.copy(); - ItemStack ostack = stackInSlot.copy(); - ostack.setCount(amount); - return ostack; - } else { - ItemStack ostack = te.decrStackSize(slotno, Math.min(stackInSlot.getCount(), amount)); - te.markDirty(); - return ostack; - } - } - } - // Capability export ---------------------------------------------------------------------------- - protected LazyOptional item_handler_ = LazyOptional.of(() -> new BItemHandler(this)); - protected LazyOptional energy_handler_ = LazyOptional.of(() -> (IEnergyStorage)this); - @Override public LazyOptional getCapability(net.minecraftforge.common.capabilities.Capability capability, @Nullable Direction facing) { @@ -491,25 +330,25 @@ public class EdElectricalFurnace if(transferItems(FIFO_INPUT_0_SLOT_NO, SMELTING_INPUT_SLOT_NO, 64)) dirty = true; if(transferItems(FIFO_INPUT_1_SLOT_NO, FIFO_INPUT_0_SLOT_NO, 64)) { dirty = true; } else { shift_in = true; } } - if(energy_stored_ < energy_consumption()) { + if(battery_.getEnergyStored() < energy_consumption()) { enabled_ = false; - } else if(energy_stored_ >= (MAX_ENERGY_BUFFER/2)) { + } else if(battery_.getEnergyStored() >= (MAX_ENERGY_BUFFER/2)) { enabled_ = true; } - if((!(stacks_.get(SMELTING_INPUT_SLOT_NO)).isEmpty()) && (enabled_) && (speed_>0)) { + if((!(inventory_.getStackInSlot(SMELTING_INPUT_SLOT_NO)).isEmpty()) && (enabled_) && (speed_>0)) { IRecipe last_recipe = currentRecipe(); updateCurrentRecipe(); if(currentRecipe() != last_recipe) { proc_time_elapsed_ = 0; - proc_time_needed_ = getSmeltingTimeNeeded(world, stacks_.get(SMELTING_INPUT_SLOT_NO)); + proc_time_needed_ = getSmeltingTimeNeeded(world, inventory_.getStackInSlot(SMELTING_INPUT_SLOT_NO)); } final boolean can_smelt = canSmeltCurrentItem(); - if((!can_smelt) && (getSmeltingResult(stacks_.get(SMELTING_INPUT_SLOT_NO)).isEmpty())) { + if((!can_smelt) && (getSmeltingResult(inventory_.getStackInSlot(SMELTING_INPUT_SLOT_NO)).isEmpty())) { // bypass if(transferItems(SMELTING_INPUT_SLOT_NO, SMELTING_OUTPUT_SLOT_NO, 1)) dirty = true; } else { // smelt, automatically choke speed on low power storage - final int speed = MathHelper.clamp((getEnergyStored()>getMaxEnergyStored()/5)? (speed_) : (1), 1, MAX_SPEED_SETTING); + final int speed = (battery_.getSOC() >= 25)? (speed_) : (1); if(!burning() && can_smelt) { if(heat_up(speed)) { dirty = true; update_blockstate = true; } } @@ -518,7 +357,7 @@ public class EdElectricalFurnace proc_time_elapsed_ += (int)(TICK_INTERVAL * proc_speed_percent_ * speed_setting_factor_[speed] / 100); if(proc_time_elapsed_ >= proc_time_needed_) { proc_time_elapsed_ = 0; - proc_time_needed_ = getSmeltingTimeNeeded(world, stacks_.get(SMELTING_INPUT_SLOT_NO)); + proc_time_needed_ = getSmeltingTimeNeeded(world, inventory_.getStackInSlot(SMELTING_INPUT_SLOT_NO)); smeltCurrentItem(); dirty = true; shift_out = true; @@ -528,7 +367,7 @@ public class EdElectricalFurnace } } } else if(proc_time_elapsed_ > 0) { - proc_time_elapsed_ -= ((stacks_.get(SMELTING_INPUT_SLOT_NO)).isEmpty() ? 20 : 1); + proc_time_elapsed_ -= ((inventory_.getStackInSlot(SMELTING_INPUT_SLOT_NO)).isEmpty() ? 20 : 1); if(proc_time_elapsed_ < 0) { proc_time_elapsed_ = 0; shift_out = true; update_blockstate = true; } } if(update_blockstate) { @@ -537,31 +376,24 @@ public class EdElectricalFurnace } if(adjacent_inventory_shift(shift_in, shift_out)) dirty = true; if(dirty) markDirty(); - field_max_energy_stored_ = getMaxEnergyStored(); - field_isburning_ = burning() ? 1 : 0; + field_is_burning_ = burning() ? 1 : 0; } // Furnace -------------------------------------------------------------------------------------- - protected void updateCurrentRecipe() - { setCurrentRecipe(getSmeltingResult(RECIPE_TYPE, world, stacks_.get(SMELTING_INPUT_SLOT_NO))); } - - public boolean burning() - { return burntime_left_ > 0; } - private boolean is_accepted_hopper(final ItemStack stack) { return (stack.getItem() == Blocks.HOPPER.asItem()) || (stack.getItem() == ModContent.FACTORY_HOPPER.asItem()); } private boolean transferItems(final int index_from, final int index_to, int count) { - ItemStack from = stacks_.get(index_from); + ItemStack from = inventory_.getStackInSlot(index_from); if(from.isEmpty()) return false; - ItemStack to = stacks_.get(index_to); + ItemStack to = inventory_.getStackInSlot(index_to); if(from.getCount() < count) count = from.getCount(); if(count <= 0) return false; boolean changed = true; if(to.isEmpty()) { - stacks_.set(index_to, from.split(count)); + inventory_.setInventorySlotContents(index_to, from.split(count)); } else if(to.getCount() >= to.getMaxStackSize()) { changed = false; } else if(Inventories.areItemStacksDifferent(from, to)) { @@ -576,7 +408,7 @@ public class EdElectricalFurnace } } if(from.isEmpty() && from!=ItemStack.EMPTY) { - stacks_.set(index_from, ItemStack.EMPTY); + inventory_.setInventorySlotContents(index_from, ItemStack.EMPTY); changed = true; } return changed; @@ -585,25 +417,25 @@ public class EdElectricalFurnace private boolean adjacent_inventory_shift(boolean inp, boolean out) { boolean dirty = false; - if(energy_stored_ < transfer_energy_consumption_) return false; + if(battery_.getEnergyStored() < transfer_energy_consumption_) return false; final BlockState state = world.getBlockState(pos); if(!(state.getBlock() instanceof ElectricalFurnaceBlock)) return false; final Direction out_facing = state.get(ElectricalFurnaceBlock.HORIZONTAL_FACING); - if(out && (!stacks_.get(FIFO_OUTPUT_1_SLOT_NO).isEmpty())) { + if(out && (!inventory_.getStackInSlot(FIFO_OUTPUT_1_SLOT_NO).isEmpty())) { TileEntity te = world.getTileEntity(pos.offset(out_facing)); if(te!=null) { IItemHandler hnd = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, out_facing).orElse(null); if(hnd != null) { - ItemStack remaining = ItemHandlerHelper.insertItemStacked(hnd, stacks_.get(FIFO_OUTPUT_1_SLOT_NO).copy(), false); - stacks_.set(FIFO_OUTPUT_1_SLOT_NO, remaining); - energy_stored_ -= transfer_energy_consumption_; + ItemStack remaining = ItemHandlerHelper.insertItemStacked(hnd, inventory_.getStackInSlot(FIFO_OUTPUT_1_SLOT_NO).copy(), false); + inventory_.setInventorySlotContents(FIFO_OUTPUT_1_SLOT_NO, remaining); + battery_.draw(transfer_energy_consumption_); dirty = true; } } } - if(with_automatic_inventory_pulling_ || is_accepted_hopper(stacks_.get(SMELTING_AUX_SLOT_NO))) { + if(with_automatic_inventory_pulling_ || is_accepted_hopper(inventory_.getStackInSlot(SMELTING_AUX_SLOT_NO))) { final Direction inp_facing = state.get(ElectricalFurnaceBlock.HORIZONTAL_FACING).getOpposite(); - if(inp && (stacks_.get(FIFO_INPUT_1_SLOT_NO).isEmpty())) { + if(inp && (inventory_.getStackInSlot(FIFO_INPUT_1_SLOT_NO).isEmpty())) { TileEntity te = world.getTileEntity(pos.offset(inp_facing)); if(te!=null) { IItemHandler hnd = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, inp_facing).orElse(null); @@ -612,10 +444,10 @@ public class EdElectricalFurnace ItemStack adj_stack = hnd.getStackInSlot(i); if(!adj_stack.isEmpty()) { ItemStack my_stack = adj_stack.copy(); - if(my_stack.getCount() > getInventoryStackLimit()) my_stack.setCount(getInventoryStackLimit()); + if(my_stack.getCount() > inventory_.getInventoryStackLimit()) my_stack.setCount(inventory_.getInventoryStackLimit()); adj_stack.shrink(my_stack.getCount()); - stacks_.set(FIFO_INPUT_1_SLOT_NO, my_stack); - energy_stored_ -= transfer_energy_consumption_; + inventory_.setInventorySlotContents(FIFO_INPUT_1_SLOT_NO, my_stack); + battery_.draw(transfer_energy_consumption_); dirty = true; break; } @@ -642,10 +474,9 @@ public class EdElectricalFurnace private boolean heat_up(int speed) { - int p = energy_consumption(speed); - if((p<=0) || (energy_stored_ < p)) return false; if(burntime_left_ >= (HEAT_CAPACITY-HEAT_INCREMENT)) return false; - energy_stored_ -= p; + int p = energy_consumption(speed); + if((p<=0) || (!battery_.draw(p))) return false; burntime_left_ += HEAT_INCREMENT; this.markDirty(); return true; // returns TE dirty @@ -689,7 +520,7 @@ public class EdElectricalFurnace inventory_ = block_inventory; wpc_ = wpc; fields_ = fields; - recipe_type_ = ElectricalFurnaceTileEntity.RECIPE_TYPE; + recipe_type_ = FurnaceTileEntity.RECIPE_TYPE; addSlot(new Slot(inventory_, 0, 59, 28)); // smelting input addSlot(new Slot(inventory_, 1, 16, 52)); // aux addSlot(new EdFurnace.FurnaceContainer.BSlotResult(player_, inventory_, 2, 101, 28)); // smelting result @@ -774,8 +605,8 @@ public class EdElectricalFurnace public void onClientPacketReceived(int windowId, PlayerEntity player, CompoundNBT nbt) { - if(!(inventory_ instanceof ElectricalFurnaceTileEntity)) return; - ElectricalFurnaceTileEntity te = (ElectricalFurnaceTileEntity)inventory_; + if(!(inventory_ instanceof StorageInventory)) return; + ElectricalFurnaceTileEntity te = (ElectricalFurnaceTileEntity)(((StorageInventory)inventory_).getTileEntity()); if(nbt.contains("speed")) te.speed_ = MathHelper.clamp(nbt.getInt("speed"), 0, ElectricalFurnaceTileEntity.MAX_SPEED_SETTING); te.markDirty(); } diff --git a/src/main/java/wile/engineersdecor/blocks/EdFluidBarrel.java b/src/main/java/wile/engineersdecor/blocks/EdFluidBarrel.java index 605ab32..8141960 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdFluidBarrel.java +++ b/src/main/java/wile/engineersdecor/blocks/EdFluidBarrel.java @@ -11,11 +11,7 @@ package wile.engineersdecor.blocks; import net.minecraft.fluid.Fluid; import net.minecraft.fluid.Fluids; import net.minecraft.util.*; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.libmc.blocks.StandardBlocks; -import wile.engineersdecor.libmc.detail.Auxiliaries; -import wile.engineersdecor.libmc.detail.Fluidics; -import wile.engineersdecor.libmc.detail.Overlay; +import net.minecraft.world.IWorldReader; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.LivingEntity; import net.minecraft.item.BlockItem; @@ -49,6 +45,11 @@ import net.minecraftforge.fluids.FluidUtil; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; +import wile.engineersdecor.ModContent; +import wile.engineersdecor.libmc.blocks.StandardBlocks; +import wile.engineersdecor.libmc.detail.Auxiliaries; +import wile.engineersdecor.libmc.detail.Fluidics; +import wile.engineersdecor.libmc.detail.Overlay; import javax.annotation.Nullable; import java.util.ArrayList; @@ -209,6 +210,10 @@ public class EdFluidBarrel return (int)MathHelper.clamp(((FluidBarrelTileEntity)te).getNormalizedFillLevel() * 15, 0, 15); } + @Override + public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) + { return false; } + } //-------------------------------------------------------------------------------------------------------------------- @@ -218,8 +223,26 @@ public class EdFluidBarrel public static class FluidBarrelTileEntity extends TileEntity implements ICapabilityProvider, ITickableTileEntity { private final int TICK_INTERVAL = 10; - private final Fluidics.Tank tank_ = new Fluidics.Tank(capacity_); private int tick_timer_ = 0; + private final Fluidics.Tank tank_; + private final LazyOptional fluid_handler_; + + public FluidBarrelTileEntity() + { this(ModContent.TET_FLUID_BARREL); } + + public FluidBarrelTileEntity(TileEntityType te_type) + { + super(te_type); + tank_ = new Fluidics.Tank(capacity_); + tank_.setInteractionNotifier((t,d)->on_tank_changed()); + fluid_handler_ = tank_.createFluidHandler(); + } + + public void readnbt(CompoundNBT nbt) + { tank_.load(nbt); } + + public CompoundNBT writenbt(CompoundNBT nbt) + { tank_.save(nbt); return nbt; } public boolean handlePlayerInteraction(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand) { @@ -256,31 +279,11 @@ public class EdFluidBarrel public double getNormalizedFillLevel() { return (tank_.isEmpty()) ? (0) : ((double)tank_.getFluidAmount()/(double)tank_.getCapacity()); } - public void readnbt(CompoundNBT nbt) - { - if(nbt.contains("tank", Constants.NBT.TAG_COMPOUND)) tank_.readnbt(nbt.getCompound("tank")); - } - - public CompoundNBT writenbt(CompoundNBT nbt) - { - if(!tank_.isEmpty()) nbt.put("tank", tank_.writenbt(new CompoundNBT())); - return nbt; - } - protected void on_tank_changed() { if(tick_timer_ > 2) tick_timer_ = 2; } // TileEntity ------------------------------------------------------------------------------ - public FluidBarrelTileEntity() - { this(ModContent.TET_FLUID_BARREL); } - - public FluidBarrelTileEntity(TileEntityType te_type) - { - super(te_type); - tank_.setInteractionNotifier((t,d)->on_tank_changed()); - } - @Override public void read(BlockState state, CompoundNBT nbt) { super.read(state, nbt); readnbt(nbt); } @@ -294,16 +297,10 @@ public class EdFluidBarrel { super.remove(); fluid_handler_.invalidate(); } public CompoundNBT clear_getnbt() - { - CompoundNBT nbt = new CompoundNBT(); - if(!tank_.isEmpty()) nbt.put("tank", tank_.writenbt(new CompoundNBT())); - return nbt; - } + { return tank_.save(new CompoundNBT()); } // ICapabilityProvider -------------------------------------------------------------------- - private final LazyOptional fluid_handler_ = LazyOptional.of(() -> new Fluidics.SingleTankFluidHandler(tank_)); - @Override public LazyOptional getCapability(net.minecraftforge.common.capabilities.Capability capability, @Nullable Direction facing) { diff --git a/src/main/java/wile/engineersdecor/blocks/EdFluidFunnel.java b/src/main/java/wile/engineersdecor/blocks/EdFluidFunnel.java index 778d3fe..6e1856e 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdFluidFunnel.java +++ b/src/main/java/wile/engineersdecor/blocks/EdFluidFunnel.java @@ -10,6 +10,7 @@ */ package wile.engineersdecor.blocks; +import net.minecraft.world.IWorldReader; import wile.engineersdecor.ModContent; import net.minecraft.block.*; import net.minecraft.entity.LivingEntity; @@ -39,8 +40,8 @@ import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; import wile.engineersdecor.ModEngineersDecor; +import wile.engineersdecor.libmc.detail.Fluidics; -import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.*; @@ -153,13 +154,17 @@ public class EdFluidFunnel @SuppressWarnings("deprecation") public void neighborChanged(BlockState state, World world, BlockPos pos, Block block, BlockPos fromPos, boolean unused) { TileEntity te = world.getTileEntity(pos); if(te instanceof FluidFunnelTileEntity) ((FluidFunnelTileEntity)te).block_changed(); } + + @Override + public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) + { return false; } } //-------------------------------------------------------------------------------------------------------------------- // Tile entity //-------------------------------------------------------------------------------------------------------------------- - public static class FluidFunnelTileEntity extends TileEntity implements ITickableTileEntity, ICapabilityProvider, IFluidTank + public static class FluidFunnelTileEntity extends TileEntity implements ITickableTileEntity, ICapabilityProvider { public static final int TANK_CAPACITY = 3000; public static final int TICK_INTERVAL = 10; // ca 500ms @@ -169,7 +174,6 @@ public class EdFluidFunnel public static final int MAX_TRACKING_STEPS_PER_CYCLE_INTENSIVE = 1024; public static final int MAX_TRACK_RADIUS_SQ = MAX_TRACK_RADIUS*MAX_TRACK_RADIUS; public static final int INTENSIVE_SEARCH_TRIGGER_THRESHOLD = 16; - private FluidStack tank_ = FluidStack.EMPTY; private int tick_timer_ = 0; private int collection_timer_ = 0; private int no_fluid_found_counter_ = 0; @@ -177,26 +181,32 @@ public class EdFluidFunnel private int total_pick_counter_ = 0; private BlockPos last_pick_pos_ = BlockPos.ZERO; private ArrayList search_offsets_ = null; - - public void block_changed() - { tick_timer_ = TICK_INTERVAL; } // collect after flowing fluid has a stable state, otherwise it looks odd. + private final Fluidics.Tank tank_; + private final LazyOptional fluid_handler_; public FluidFunnelTileEntity() { this(ModContent.TET_SMALL_FLUID_FUNNEL); } public FluidFunnelTileEntity(TileEntityType te_type) - { super(te_type); } + { + super(te_type); + tank_ = new Fluidics.Tank(TANK_CAPACITY, 0, TANK_CAPACITY); + fluid_handler_ = tank_.createOutputFluidHandler(); + } public void readnbt(CompoundNBT nbt) { - tank_ = (!nbt.contains("tank")) ? (FluidStack.EMPTY) : (FluidStack.loadFluidStackFromNBT(nbt.getCompound("tank"))); + tank_.load(nbt); } public void writenbt(CompoundNBT nbt) { - if(!tank_.isEmpty()) nbt.put("tank", tank_.writeToNBT(new CompoundNBT())); + tank_.save(nbt); } + public void block_changed() + { tick_timer_ = TICK_INTERVAL; } + // TileEntity ----------------------------------------------------------------------------------------- @Override @@ -216,20 +226,7 @@ public class EdFluidFunnel // ICapabilityProvider / Output flow handler ---------------------------------------------------------- - private static class OutputFluidHandler implements IFluidHandler - { - private final FluidFunnelTileEntity te; - OutputFluidHandler(FluidFunnelTileEntity parent) { te = parent; } - @Override public int getTanks() { return 1; } - @Override public FluidStack getFluidInTank(int tank) { return te.tank_.copy(); } - @Override public int getTankCapacity(int tank) { return TANK_CAPACITY; } - @Override public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { return true; } - @Override public int fill(FluidStack resource, FluidAction action) { return 0; } - @Override public FluidStack drain(FluidStack resource, FluidAction action) { return te.drain(resource, action); } - @Override public FluidStack drain(int maxDrain, FluidAction action) { return te.drain(maxDrain, action); } - } - private final LazyOptional fluid_handler_ = LazyOptional.of(() -> new OutputFluidHandler(this)); @Override public LazyOptional getCapability(net.minecraftforge.common.capabilities.Capability capability, @Nullable Direction facing) @@ -238,56 +235,10 @@ public class EdFluidFunnel return super.getCapability(capability, facing); } - // IFluidTank ------------------------------------------------------------------------------------------ - - @Override - @Nonnull - public FluidStack getFluid() - { return tank_.copy(); } - - @Override - public int getFluidAmount() - { return tank_.getAmount(); } - - @Override - public int getCapacity() - { return TANK_CAPACITY; } - - @Override - public boolean isFluidValid(FluidStack stack) - { return true; } - - @Override - public int fill(FluidStack resource, FluidAction action) - { return 0; } - - @Override - @Nonnull - public FluidStack drain(FluidStack resource, FluidAction action) - { - if((resource==null) || (tank_.isEmpty())) return FluidStack.EMPTY; - return (!(tank_.isFluidEqual(resource))) ? (FluidStack.EMPTY) : drain(resource.getAmount(), action); - } - - @Override - @Nonnull - public FluidStack drain(int maxDrain, FluidAction action) - { - if(tank_.isEmpty()) return FluidStack.EMPTY; - FluidStack res = tank_.copy(); - maxDrain = MathHelper.clamp(maxDrain ,0 , tank_.getAmount()); - res.setAmount(maxDrain); - if(action != FluidAction.EXECUTE) return res; - tank_.setAmount(tank_.getAmount()-maxDrain); - if(tank_.getAmount() <= 0) tank_ = FluidStack.EMPTY; - return res; - } - // ITickableTileEntity -------------------------------------------------------------------------------- private FluidState get_fluidstate(BlockPos pos) { - // todo: check if getFluidState() is enough final Block collection_block = world.getBlockState(pos).getBlock(); if((!(collection_block instanceof IFluidBlock)) && (!(collection_block instanceof FlowingFluidBlock)) && (!(collection_block instanceof IWaterLoggable))) { return Fluids.EMPTY.getDefaultState(); @@ -313,9 +264,9 @@ public class EdFluidFunnel } if((fs==null) || (fs.isEmpty())) return false; // it's marked nonnull but I don't trust every modder - including meself ... if(tank_.isEmpty()) { - tank_ = fs.copy(); + tank_.setFluid(fs.copy()); } else if(tank_.isFluidEqual(fs)) { - tank_.setAmount(MathHelper.clamp(tank_.getAmount()+fs.getAmount(), 0, TANK_CAPACITY)); + tank_.fill(fs, FluidAction.EXECUTE); } else { return false; } @@ -352,7 +303,7 @@ public class EdFluidFunnel FluidState collection_fluidstate = get_fluidstate(collection_pos); if(collection_fluidstate.isEmpty()) return false; Fluid fluid_to_collect = collection_fluidstate.getFluid(); - if((!tank_.isEmpty()) && (!tank_.getFluid().isEquivalentTo(fluid_to_collect))) return false; + if((!tank_.isEmpty()) && (!tank_.getFluid().getFluid().isEquivalentTo(fluid_to_collect))) return false; if(try_pick(collection_pos, collection_fluidstate)) { last_pick_pos_ = collection_pos; return true; } // Blocks directly always first. Allows water source blocks to recover/reflow to source blocks. if((last_pick_pos_==null) || (last_pick_pos_.distanceSq(collection_pos) > MAX_TRACK_RADIUS_SQ)) { last_pick_pos_ = collection_pos; search_offsets_ = null; } BlockPos pos = last_pick_pos_; @@ -420,7 +371,7 @@ public class EdFluidFunnel if(!(funnel_state.getBlock() instanceof FluidFunnelBlock)) return; boolean dirty = false; // Collection - if((collection_timer_ >= COLLECTION_INTERVAL) && ((tank_==null) || (tank_.getAmount() <= (TANK_CAPACITY-1000)))) { + if((collection_timer_ >= COLLECTION_INTERVAL) && ((tank_==null) || (tank_.getFluidAmount() <= (TANK_CAPACITY-1000)))) { collection_timer_ = 0; if(!world.isBlockPowered(pos)) { // redstone disable feature if(last_pick_pos_==null) last_pick_pos_ = pos.up(); @@ -431,12 +382,11 @@ public class EdFluidFunnel te = null; } else if(tank_.isEmpty()) { FluidStack fs = fh.drain(1000, FluidAction.EXECUTE); - if((fs!=null) && (!fs.isEmpty())) tank_ = fs.copy(); + if((fs!=null) && (!fs.isEmpty())) tank_.setFluid(fs.copy()); dirty = true; - } else { - FluidStack todrain = new FluidStack(tank_.getFluid(), 1000); - FluidStack fs = fh.drain(todrain, FluidAction.EXECUTE); - if((fs!=null) && (!fs.isEmpty())) tank_.setAmount(tank_.getAmount()+fs.getAmount()); + } else if (!tank_.isFull()) { + FluidStack todrain = new FluidStack(tank_.getFluid(), Math.min(tank_.getCapacity()-tank_.getFluidAmount(), 1000)); + tank_.fill(fh.drain(todrain, FluidAction.EXECUTE), FluidAction.EXECUTE); dirty = true; } } @@ -446,17 +396,17 @@ public class EdFluidFunnel } } // Gravity fluid transfer - if((tank_.getAmount() >= 1000)) { + if((tank_.getFluidAmount() >= 1000)) { IFluidHandler fh = FluidUtil.getFluidHandler(world, pos.down(), Direction.UP).orElse(null); if(fh != null) { - FluidStack fs = new FluidStack(tank_.getFluid(), 1000); + FluidStack fs = new FluidStack(tank_.getFluid().getFluid(), 1000); int nfilled = MathHelper.clamp(fh.fill(fs, FluidAction.EXECUTE), 0, 1000); - tank_.shrink(nfilled); + tank_.drain(nfilled); dirty = true; } } // Block state - int fill_level = (tank_==null) ? 0 : (MathHelper.clamp(tank_.getAmount()/1000,0, FluidFunnelBlock.FILL_LEVEL_MAX)); + int fill_level = (tank_==null) ? 0 : (MathHelper.clamp(tank_.getFluidAmount()/1000,0, FluidFunnelBlock.FILL_LEVEL_MAX)); if(funnel_state.get(FluidFunnelBlock.FILL_LEVEL) != fill_level) world.setBlockState(pos, funnel_state.with(FluidFunnelBlock.FILL_LEVEL, fill_level), 2|16); if(dirty) markDirty(); } diff --git a/src/main/java/wile/engineersdecor/blocks/EdFreezer.java b/src/main/java/wile/engineersdecor/blocks/EdFreezer.java index 6758673..4b80424 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdFreezer.java +++ b/src/main/java/wile/engineersdecor/blocks/EdFreezer.java @@ -9,9 +9,7 @@ */ package wile.engineersdecor.blocks; -import net.minecraftforge.common.util.Constants; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.ModEngineersDecor; +import net.minecraft.world.IWorldReader; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; import net.minecraft.block.*; @@ -40,6 +38,8 @@ import net.minecraftforge.items.IItemHandler; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import wile.engineersdecor.libmc.detail.Fluidics; +import wile.engineersdecor.ModContent; +import wile.engineersdecor.ModEngineersDecor; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -135,6 +135,10 @@ public class EdFreezer } } + @Override + public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) + { return false; } + @Override @OnlyIn(Dist.CLIENT) public void animateTick(BlockState state, World world, BlockPos pos, Random rnd) @@ -155,6 +159,7 @@ public class EdFreezer public static final int MAX_FLUID_LEVEL = 2000; public static final int MAX_ENERGY_BUFFER = 32000; public static final int MAX_ENERGY_TRANSFER = 8192; + public static final int TANK_CAPACITY = 2000; public static final int DEFAULT_ENERGY_CONSUMPTION = 92; public static final int DEFAULT_COOLDOWN_RATE = 2; public static final int PHASE_EMPTY = 0; @@ -166,7 +171,7 @@ public class EdFreezer private static int energy_consumption = DEFAULT_ENERGY_CONSUMPTION; private static int cooldown_rate = DEFAULT_COOLDOWN_RATE; private static int reheat_rate = 1; - private final Fluidics.Tank tank_ = new Fluidics.Tank(2000, fs->fs.getFluid()==Fluids.WATER); + private final Fluidics.Tank tank_ = new Fluidics.Tank(TANK_CAPACITY, TANK_CAPACITY, TANK_CAPACITY, fs->fs.getFluid()==Fluids.WATER); private int tick_timer_; private int energy_stored_; private int progress_; @@ -226,14 +231,14 @@ public class EdFreezer { energy_stored_ = nbt.getInt("energy"); progress_ = nbt.getInt("progress"); - if(nbt.contains("tank", Constants.NBT.TAG_COMPOUND)) tank_.readnbt(nbt.getCompound("tank")); + tank_.load(nbt); } protected void writenbt(CompoundNBT nbt) { nbt.putInt("energy", MathHelper.clamp(energy_stored_,0 , MAX_ENERGY_BUFFER)); nbt.putInt("progress", MathHelper.clamp(progress_,0 , 100)); - if(!tank_.isEmpty()) nbt.put("tank", tank_.writenbt(new CompoundNBT())); + tank_.save(nbt); } // TileEntity ------------------------------------------------------------------------------ diff --git a/src/main/java/wile/engineersdecor/blocks/EdFurnace.java b/src/main/java/wile/engineersdecor/blocks/EdFurnace.java index f947da7..a21bfaf 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdFurnace.java +++ b/src/main/java/wile/engineersdecor/blocks/EdFurnace.java @@ -29,6 +29,7 @@ import net.minecraft.state.StateContainer; import net.minecraft.util.text.StringTextComponent; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.world.IWorldReader; import net.minecraft.world.World; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; @@ -53,13 +54,16 @@ import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.energy.IEnergyStorage; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.wrapper.SidedInvWrapper; import wile.engineersdecor.ModContent; import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.detail.ExternalObjects; import wile.engineersdecor.libmc.client.ContainerGui; import wile.engineersdecor.libmc.detail.Inventories; +import wile.engineersdecor.libmc.detail.Inventories.StorageInventory; +import wile.engineersdecor.libmc.detail.Inventories.MappedItemHandler; import wile.engineersdecor.libmc.detail.Networking; +import wile.engineersdecor.libmc.detail.RfEnergy; + import javax.annotation.Nullable; import java.util.*; @@ -104,6 +108,10 @@ public class EdFurnace return (te instanceof FurnaceTileEntity) ? ((FurnaceTileEntity)te).getComparatorOutput() : 0; } + @Override + public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) + { return false; } + @Override public boolean hasTileEntity(BlockState state) { return true; } @@ -148,7 +156,7 @@ public class EdFurnace } stacks.add(stack); } else { - for(ItemStack stack: ((FurnaceTileEntity)te).stacks_) stacks.add(stack); + for(ItemStack stack: ((FurnaceTileEntity)te).inventory_) stacks.add(stack); ((FurnaceTileEntity)te).reset(); } return stacks; @@ -190,27 +198,28 @@ public class EdFurnace // Tile entity //-------------------------------------------------------------------------------------------------------------------- - public static class FurnaceTileEntity extends TileEntity implements ITickableTileEntity, INameable, IInventory, INamedContainerProvider, ISidedInventory, IEnergyStorage + public static class FurnaceTileEntity extends TileEntity implements ITickableTileEntity, INameable, INamedContainerProvider { - public static final IRecipeType RECIPE_TYPE = IRecipeType.SMELTING; - public static final int NUM_OF_FIELDS = 5; - public static final int TICK_INTERVAL = 4; - public static final int FIFO_INTERVAL = 20; - public static final int STD_SMELTING_TIME = 200; - public static final int MAX_BURNTIME = 0x7fff; - public static final int DEFAULT_BOOST_ENERGY = 32; - public static final int NUM_OF_SLOTS = 11; - public static final int SMELTING_INPUT_SLOT_NO = 0; - public static final int SMELTING_FUEL_SLOT_NO = 1; - public static final int SMELTING_OUTPUT_SLOT_NO = 2; - public static final int FIFO_INPUT_0_SLOT_NO = 3; - public static final int FIFO_INPUT_1_SLOT_NO = 4; - public static final int FIFO_FUEL_0_SLOT_NO = 5; - public static final int FIFO_FUEL_1_SLOT_NO = 6; - public static final int FIFO_OUTPUT_0_SLOT_NO = 7; - public static final int FIFO_OUTPUT_1_SLOT_NO = 8; - public static final int AUX_0_SLOT_NO = 9; - public static final int AUX_1_SLOT_NO =10; + protected static final IRecipeType RECIPE_TYPE = IRecipeType.SMELTING; + private static final int MAX_BURNTIME = 0x7fff; + private static final int MAX_XP_STORED = 65535; + private static final int NUM_OF_FIELDS = 5; + private static final int TICK_INTERVAL = 4; + private static final int FIFO_INTERVAL = 20; + private static final int DEFAULT_SMELTING_TIME = 200; + private static final int DEFAULT_BOOST_ENERGY = 32; + private static final int NUM_OF_SLOTS = 11; + private static final int SMELTING_INPUT_SLOT_NO = 0; + private static final int SMELTING_FUEL_SLOT_NO = 1; + private static final int SMELTING_OUTPUT_SLOT_NO = 2; + private static final int FIFO_INPUT_0_SLOT_NO = 3; + private static final int FIFO_INPUT_1_SLOT_NO = 4; + private static final int FIFO_FUEL_0_SLOT_NO = 5; + private static final int FIFO_FUEL_1_SLOT_NO = 6; + private static final int FIFO_OUTPUT_0_SLOT_NO = 7; + private static final int FIFO_OUTPUT_1_SLOT_NO = 8; + private static final int AUX_0_SLOT_NO = 9; + private static final int AUX_1_SLOT_NO =10; // Config ---------------------------------------------------------------------------------- @@ -228,26 +237,81 @@ public class EdFurnace // DecorFurnaceTileEntity ----------------------------------------------------------------------------- - private int tick_timer_; - private int fifo_timer_; - private int burntime_left_; - private int fuel_burntime_; - private double proc_time_elapsed_; - private int proc_time_needed_; - private int field_is_burning_; - private int field_proc_time_elapsed_; - - private int boost_energy_; // small, not saved in nbt. - private boolean heater_inserted_ = false; - protected NonNullList stacks_; + protected int tick_timer_; + protected int fifo_timer_; + protected double proc_time_elapsed_; + protected int proc_time_needed_; + protected int burntime_left_; + protected int field_is_burning_; + protected float xp_stored_; protected @Nullable IRecipe current_recipe_ = null; - private final List recent_recipes_ = new ArrayList<>(); + private int fuel_burntime_; + private int field_proc_time_elapsed_; + private boolean heater_inserted_ = false; + protected final RfEnergy.Battery battery_; + protected final StorageInventory inventory_; + protected final LazyOptional energy_handler_; + private final LazyOptional item_extraction_handler_; + private final LazyOptional item_insertion_handler_; + private final LazyOptional item_fuel_insertion_handler_; public FurnaceTileEntity() { this(ModContent.TET_SMALL_LAB_FURNACE); } public FurnaceTileEntity(TileEntityType te_type) - { super(te_type); reset(); } + { this(te_type, NUM_OF_SLOTS); } + + public FurnaceTileEntity(TileEntityType te_type, int num_slots) + { + super(te_type); + inventory_ = new StorageInventory(this, num_slots) { + @Override + public void setInventorySlotContents(int index, ItemStack stack) + { + ItemStack slot_stack = stacks_.get(index); + boolean already_in_slot = (!stack.isEmpty()) && (Inventories.areItemStacksIdentical(stack, slot_stack)); + stacks_.set(index, stack); + if(stack.getCount() > getInventoryStackLimit()) stack.setCount(getInventoryStackLimit()); + if((index == SMELTING_INPUT_SLOT_NO) && (!already_in_slot)) { + proc_time_needed_ = getSmeltingTimeNeeded(world, stack); + proc_time_elapsed_ = 0; + markDirty(); + } + } + }; + inventory_.setValidator((index, stack)->{ + // applies to gui and handlers + switch(index) { + case SMELTING_OUTPUT_SLOT_NO: + case FIFO_OUTPUT_0_SLOT_NO: + case FIFO_OUTPUT_1_SLOT_NO: + return false; + case SMELTING_INPUT_SLOT_NO: + case FIFO_INPUT_0_SLOT_NO: + case FIFO_INPUT_1_SLOT_NO: + return true; + case AUX_0_SLOT_NO: + case AUX_1_SLOT_NO: + return true; + default: { + ItemStack slot_stack = inventory_.getStackInSlot(FIFO_FUEL_1_SLOT_NO); + return isFuel(world, stack) || FurnaceFuelSlot.isBucket(stack) && (slot_stack.getItem() != Items.BUCKET); + } + } + }); + item_extraction_handler_ = MappedItemHandler.createExtractionHandler(inventory_, + (slot,stack)->(slot!=SMELTING_FUEL_SLOT_NO) || (stack.getItem()==Items.BUCKET) || (!isFuel(getWorld(), stack)), + Arrays.asList(FIFO_OUTPUT_0_SLOT_NO, FIFO_OUTPUT_1_SLOT_NO, SMELTING_FUEL_SLOT_NO) + ); + item_insertion_handler_ = MappedItemHandler.createInsertionHandler(inventory_, + FIFO_INPUT_1_SLOT_NO,FIFO_INPUT_0_SLOT_NO,SMELTING_INPUT_SLOT_NO + ); + item_fuel_insertion_handler_ = MappedItemHandler.createInsertionHandler(inventory_, + FIFO_FUEL_1_SLOT_NO,FIFO_FUEL_0_SLOT_NO,SMELTING_FUEL_SLOT_NO + ); + battery_ = new RfEnergy.Battery(boost_energy_consumption * 16, boost_energy_consumption, 0); + energy_handler_ = battery_.createEnergyHandler(); + } public CompoundNBT reset_getnbt() { @@ -259,53 +323,48 @@ public class EdFurnace public void reset() { - stacks_ = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); + inventory_.clear(); proc_time_elapsed_ = 0; proc_time_needed_ = 0; burntime_left_ = 0; fuel_burntime_ = 0; fifo_timer_ = 0; tick_timer_ = 0; + xp_stored_ = 0; current_recipe_ = null; } public void readnbt(CompoundNBT nbt) { - ItemStackHelper.loadAllItems(nbt, stacks_); - while(stacks_.size() < NUM_OF_SLOTS) stacks_.add(ItemStack.EMPTY); burntime_left_ = nbt.getInt("BurnTime"); proc_time_elapsed_ = nbt.getInt("CookTime"); proc_time_needed_ = nbt.getInt("CookTimeTotal"); fuel_burntime_ = nbt.getInt("FuelBurnTime"); - CompoundNBT rr = nbt.getCompound("Recipes"); - for(int i=0; i getInventoryStackLimit()) stack.setCount(getInventoryStackLimit()); - if((index == SMELTING_INPUT_SLOT_NO) && (!already_in_slot)) { - proc_time_needed_ = getSmeltingTimeNeeded(world, stack); - proc_time_elapsed_ = 0; - markDirty(); - } - } - - @Override - public int getInventoryStackLimit() - { return 64; } - - @Override - public void markDirty() - { super.markDirty(); } - - @Override - public boolean isUsableByPlayer(PlayerEntity player) - { return ((getWorld().getTileEntity(getPos()) == this)) && (getPos().distanceSq(player.getPosition()) < 64); } - - @Override - public void openInventory(PlayerEntity player) - {} - - @Override - public void closeInventory(PlayerEntity player) - { markDirty(); } - - @Override - public boolean isItemValidForSlot(int index, ItemStack stack) - { - switch(index) { - case SMELTING_OUTPUT_SLOT_NO: - case FIFO_OUTPUT_0_SLOT_NO: - case FIFO_OUTPUT_1_SLOT_NO: - return false; - case SMELTING_INPUT_SLOT_NO: - case FIFO_INPUT_0_SLOT_NO: - case FIFO_INPUT_1_SLOT_NO: - return true; - case AUX_0_SLOT_NO: - case AUX_1_SLOT_NO: - return true; - default: { - ItemStack slot_stack = stacks_.get(FIFO_FUEL_1_SLOT_NO); - return isFuel(world, stack) || FurnaceFuelSlot.isBucket(stack) && (slot_stack.getItem() != Items.BUCKET); - } - } - } - - @Override - public void clear() - { stacks_.clear(); } + { return new FurnaceContainer(id, inventory, inventory_, IWorldPosCallable.of(world, pos), fields); } // Fields ----------------------------------------------------------------------------------------------- @@ -463,73 +442,15 @@ public class EdFurnace } }; - // ISidedInventory ---------------------------------------------------------------------------- - - private static final int[] SLOTS_TOP = new int[] {FIFO_INPUT_1_SLOT_NO}; - private static final int[] SLOTS_BOTTOM = new int[] {FIFO_OUTPUT_1_SLOT_NO}; - private static final int[] SLOTS_SIDES = new int[] {FIFO_FUEL_1_SLOT_NO}; - - @Override - public int[] getSlotsForFace(Direction side) - { - if(side == Direction.DOWN) return SLOTS_BOTTOM; - if(side == Direction.UP) return SLOTS_TOP; - return SLOTS_SIDES; - } - - @Override - public boolean canInsertItem(int index, ItemStack itemStackIn, Direction direction) - { return ((index==FIFO_INPUT_1_SLOT_NO) || (index==FIFO_INPUT_0_SLOT_NO) || (index==FIFO_FUEL_1_SLOT_NO) || (index==FIFO_FUEL_0_SLOT_NO)) && isItemValidForSlot(index, itemStackIn); } - - @Override - public boolean canExtractItem(int index, ItemStack stack, Direction direction) - { - if((direction!=Direction.DOWN) || ((index!=SMELTING_FUEL_SLOT_NO) && (index!=FIFO_FUEL_0_SLOT_NO) && (index!=FIFO_FUEL_1_SLOT_NO) )) return true; - return (stack.getItem()==Items.BUCKET); - } - - // IEnergyStorage ---------------------------------------------------------------------------- - - @Override - public boolean canExtract() - { return false; } - - @Override - public boolean canReceive() - { return true; } - - @Override - public int getMaxEnergyStored() - { return boost_energy_consumption; } - - @Override - public int getEnergyStored() - { return boost_energy_; } - - @Override - public int extractEnergy(int maxExtract, boolean simulate) - { return 0; } - - @Override - public int receiveEnergy(int maxReceive, boolean simulate) - { // only speedup support, no buffering, not in nbt -> no markdirty - if((boost_energy_ >= boost_energy_consumption) || (maxReceive < boost_energy_consumption)) return 0; - if(!simulate) boost_energy_ = boost_energy_consumption; - return boost_energy_consumption; - } - // Capability export ---------------------------------------------------------------------------- - LazyOptional[] item_handlers = SidedInvWrapper.create(this, Direction.UP, Direction.DOWN, Direction.NORTH); - protected LazyOptional energy_handler_ = LazyOptional.of(() -> (IEnergyStorage)this); - @Override public LazyOptional getCapability(net.minecraftforge.common.capabilities.Capability capability, @Nullable Direction facing) { if(capability==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { - if(facing == Direction.UP) return item_handlers[0].cast(); - if(facing == Direction.DOWN) return item_handlers[1].cast(); - return item_handlers[2].cast(); + if(facing == Direction.UP) return item_insertion_handler_.cast(); + if(facing == Direction.DOWN) return item_extraction_handler_.cast(); + return item_fuel_insertion_handler_.cast(); } else if(capability== CapabilityEnergy.ENERGY) { return energy_handler_.cast(); } @@ -560,17 +481,16 @@ public class EdFurnace if(transferItems(FIFO_INPUT_0_SLOT_NO, SMELTING_INPUT_SLOT_NO, 1)) dirty = true; if(transferItems(FIFO_INPUT_1_SLOT_NO, FIFO_INPUT_0_SLOT_NO, 1)) dirty = true; heater_inserted_ = (ExternalObjects.IE_EXTERNAL_HEATER==null) // without IE always allow electrical boost - || (stacks_.get(AUX_0_SLOT_NO).getItem()==ExternalObjects.IE_EXTERNAL_HEATER) - || (stacks_.get(AUX_1_SLOT_NO).getItem()==ExternalObjects.IE_EXTERNAL_HEATER); - if(!burning()) cleanupRecentRecipes(); + || (inventory_.getStackInSlot(AUX_0_SLOT_NO).getItem()==ExternalObjects.IE_EXTERNAL_HEATER) + || (inventory_.getStackInSlot(AUX_1_SLOT_NO).getItem()==ExternalObjects.IE_EXTERNAL_HEATER); } - ItemStack fuel = stacks_.get(SMELTING_FUEL_SLOT_NO); - if(burning() || (!fuel.isEmpty()) && (!(stacks_.get(SMELTING_INPUT_SLOT_NO)).isEmpty())) { + ItemStack fuel = inventory_.getStackInSlot(SMELTING_FUEL_SLOT_NO); + if(burning() || (!fuel.isEmpty()) && (!(inventory_.getStackInSlot(SMELTING_INPUT_SLOT_NO)).isEmpty())) { IRecipe last_recipe = currentRecipe(); updateCurrentRecipe(); if(currentRecipe() != last_recipe) { proc_time_elapsed_ = 0; - proc_time_needed_ = getSmeltingTimeNeeded(world, stacks_.get(SMELTING_INPUT_SLOT_NO)); + proc_time_needed_ = getSmeltingTimeNeeded(world, inventory_.getStackInSlot(SMELTING_INPUT_SLOT_NO)); } if(!burning() && canSmeltCurrentItem()) { burntime_left_ = (int)MathHelper.clamp((proc_fuel_efficiency_ * getFuelBurntime(world, fuel)), 0, MAX_BURNTIME); @@ -580,19 +500,18 @@ public class EdFurnace if(!fuel.isEmpty()) { Item fuel_item = fuel.getItem(); fuel.shrink(1); - if(fuel.isEmpty()) stacks_.set(SMELTING_FUEL_SLOT_NO, fuel_item.getContainerItem(fuel)); + if(fuel.isEmpty()) inventory_.setInventorySlotContents(SMELTING_FUEL_SLOT_NO, fuel_item.getContainerItem(fuel)); } } } if(burning() && canSmeltCurrentItem()) { proc_time_elapsed_ += TICK_INTERVAL * proc_speed_; - if(heater_inserted_ && (boost_energy_ >= boost_energy_consumption)) { - boost_energy_ = 0; + if(heater_inserted_ && battery_.draw(boost_energy_consumption)) { proc_time_elapsed_ += (TICK_INTERVAL * proc_speed_)*2; } if(proc_time_elapsed_ >= proc_time_needed_) { proc_time_elapsed_ = 0; - proc_time_needed_ = getSmeltingTimeNeeded(world, stacks_.get(SMELTING_INPUT_SLOT_NO)); + proc_time_needed_ = getSmeltingTimeNeeded(world, inventory_.getStackInSlot(SMELTING_INPUT_SLOT_NO)); smeltCurrentItem(); dirty = true; } @@ -624,10 +543,6 @@ public class EdFurnace return world.getRecipeManager().getRecipe(recipe_type, inventory, world).orElse(null); } - @Nullable - protected IRecipe currentRecipe() - { return current_recipe_; } - public boolean burning() { return burntime_left_ > 0; } @@ -637,19 +552,19 @@ public class EdFurnace AbstractCookingRecipe recipe = getSmeltingResult(RECIPE_TYPE, world, stack); if(recipe == null) return 0; int t = recipe.getCookTime(); - return (t<=0) ? STD_SMELTING_TIME : t; + return (t<=0) ? DEFAULT_SMELTING_TIME : t; } private boolean transferItems(final int index_from, final int index_to, int count) { - ItemStack from = stacks_.get(index_from); + ItemStack from = inventory_.getStackInSlot(index_from); if(from.isEmpty()) return false; - ItemStack to = stacks_.get(index_to); + ItemStack to = inventory_.getStackInSlot(index_to); if(from.getCount() < count) count = from.getCount(); if(count <= 0) return false; boolean changed = true; if(to.isEmpty()) { - stacks_.set(index_to, from.split(count)); + inventory_.setInventorySlotContents(index_to, from.split(count)); } else if(to.getCount() >= to.getMaxStackSize()) { changed = false; } else if(Inventories.areItemStacksDifferent(from, to)) { @@ -664,7 +579,7 @@ public class EdFurnace } } if(from.isEmpty() && from!=ItemStack.EMPTY) { - stacks_.set(index_from, ItemStack.EMPTY); + inventory_.setInventorySlotContents(index_from, ItemStack.EMPTY); changed = true; } return changed; @@ -672,29 +587,30 @@ public class EdFurnace protected boolean canSmeltCurrentItem() { - if((currentRecipe()==null) || (stacks_.get(SMELTING_INPUT_SLOT_NO).isEmpty())) return false; - final ItemStack recipe_result_items = getSmeltingResult(stacks_.get(SMELTING_INPUT_SLOT_NO)); + if((currentRecipe()==null) || (inventory_.getStackInSlot(SMELTING_INPUT_SLOT_NO).isEmpty())) return false; + final ItemStack recipe_result_items = getSmeltingResult(inventory_.getStackInSlot(SMELTING_INPUT_SLOT_NO)); if(recipe_result_items.isEmpty()) return false; - final ItemStack result_stack = stacks_.get(SMELTING_OUTPUT_SLOT_NO); + final ItemStack result_stack = inventory_.getStackInSlot(SMELTING_OUTPUT_SLOT_NO); if(result_stack.isEmpty()) return true; if(!result_stack.isItemEqual(recipe_result_items)) return false; - if(result_stack.getCount() + recipe_result_items.getCount() <= getInventoryStackLimit() && result_stack.getCount() + recipe_result_items.getCount() <= result_stack.getMaxStackSize()) return true; + if(result_stack.getCount() + recipe_result_items.getCount() <= inventory_.getInventoryStackLimit() && result_stack.getCount() + recipe_result_items.getCount() <= result_stack.getMaxStackSize()) return true; return result_stack.getCount() + recipe_result_items.getCount() <= recipe_result_items.getMaxStackSize(); } protected void smeltCurrentItem() { if(!canSmeltCurrentItem()) return; - final ItemStack smelting_input_stack = stacks_.get(SMELTING_INPUT_SLOT_NO); + final ItemStack smelting_input_stack = inventory_.getStackInSlot(SMELTING_INPUT_SLOT_NO); final ItemStack recipe_result_items = getSmeltingResult(smelting_input_stack); - final ItemStack smelting_output_stack = stacks_.get(SMELTING_OUTPUT_SLOT_NO); - final ItemStack fuel_stack = stacks_.get(SMELTING_FUEL_SLOT_NO); + final ItemStack smelting_output_stack = inventory_.getStackInSlot(SMELTING_OUTPUT_SLOT_NO); + final float xp = getCurrentSmeltingXp(smelting_output_stack); if(smelting_output_stack.isEmpty()) { - stacks_.set(SMELTING_OUTPUT_SLOT_NO, recipe_result_items.copy()); + inventory_.setInventorySlotContents(SMELTING_OUTPUT_SLOT_NO, recipe_result_items.copy()); } else if(smelting_output_stack.getItem() == recipe_result_items.getItem()) { smelting_output_stack.grow(recipe_result_items.getCount()); } smelting_input_stack.shrink(1); + xp_stored_ += xp; } public static int getFuelBurntime(World world, ItemStack stack) @@ -705,50 +621,39 @@ public class EdFurnace } public static boolean isFuel(World world, ItemStack stack) - { return getFuelBurntime(world, stack) > 0; } + { return (getFuelBurntime(world, stack) > 0) || (stack.getItem()==Items.LAVA_BUCKET); } - public float getSmeltingExperience(ItemStack stack) + public int consumeSmeltingExperience(ItemStack stack) { - // This method is not often needed, so the time managing dealing with the recent - // recipes is mainly invested here. - float xp = stack.getItem().getSmeltingExperience(stack); - if(xp >= 0) return xp; - for(int i=0; i= 15) xp /= 2; + xp = Math.min((float)Math.floor(xp), 150); + xp_stored_ -= xp; + return (int)xp; } public ItemStack getSmeltingResult(final ItemStack stack) { return (currentRecipe()==null) ? (ItemStack.EMPTY) : (currentRecipe().getRecipeOutput()); } + public float getCurrentSmeltingXp(final ItemStack stack) + { + float xp = (currentRecipe() instanceof AbstractCookingRecipe) ? (((AbstractCookingRecipe)currentRecipe()).getExperience()) : (stack.getItem().getSmeltingExperience(stack)); + return (xp <= 0) ? 0.7f : xp; // default value for recipes without defined xp + } + public static boolean canSmelt(World world, final ItemStack stack) { return getSmeltingResult(RECIPE_TYPE, world, stack) != null; } + @Nullable + protected IRecipe currentRecipe() + { return current_recipe_; } + protected void updateCurrentRecipe() - { setCurrentRecipe(getSmeltingResult(RECIPE_TYPE, world, stacks_.get(SMELTING_INPUT_SLOT_NO))); } + { setCurrentRecipe(getSmeltingResult(RECIPE_TYPE, getWorld(), inventory_.getStackInSlot(SMELTING_INPUT_SLOT_NO))); } protected void setCurrentRecipe(IRecipe recipe) - { - if(recipe == null) { current_recipe_ = null; return; } - current_recipe_ = recipe; - String recipe_id = recipe.getId().toString(); - if(!recent_recipes_.contains(recipe_id)) recent_recipes_.add(recipe_id); - } - - private void cleanupRecentRecipes() - { - if(recent_recipes_.isEmpty()) return; - if(!stacks_.get(SMELTING_INPUT_SLOT_NO).isEmpty()) return; - if(!stacks_.get(SMELTING_OUTPUT_SLOT_NO).isEmpty()) return; - if(!stacks_.get(FIFO_OUTPUT_0_SLOT_NO).isEmpty()) return; - if(!stacks_.get(FIFO_OUTPUT_1_SLOT_NO).isEmpty()) return; - recent_recipes_.clear(); - } - + { current_recipe_ = recipe; } } //-------------------------------------------------------------------------------------------------------------------- @@ -806,15 +711,9 @@ public class EdFurnace protected void onCrafting(ItemStack stack) { stack.onCrafting(player_.world, player_, removeCount); - if((!player_.world.isRemote) && (inventory_ instanceof FurnaceTileEntity)) { - FurnaceTileEntity te = (FurnaceTileEntity)inventory_; - int xp = removeCount; - float sxp = te.getSmeltingExperience(stack); - if(sxp == 0) { - xp = 0; - } else if(sxp < 1.0) { - xp = (int)((sxp*xp) + Math.round(Math.random()+0.75)); - } + if((!player_.world.isRemote()) && (inventory_ instanceof StorageInventory)) { + FurnaceTileEntity te = (FurnaceTileEntity)(((StorageInventory)inventory_).getTileEntity()); + int xp = te.consumeSmeltingExperience(stack); while(xp > 0) { int k = ExperienceOrbEntity.getXPSplit(xp); xp -= k; @@ -1024,7 +923,7 @@ public class EdFurnace { final int tc=getContainer().field(2), T=getContainer().field(3); return ((T>0) && (tc>0)) ? (tc * pixels / T) : (0); } private int flame_px(int pixels) - { int ibt = getContainer().field(1); return ((getContainer().field(0) * pixels) / ((ibt>0) ? (ibt) : (FurnaceTileEntity.STD_SMELTING_TIME))); } + { int ibt = getContainer().field(1); return ((getContainer().field(0) * pixels) / ((ibt>0) ? (ibt) : (FurnaceTileEntity.DEFAULT_SMELTING_TIME))); } } } diff --git a/src/main/java/wile/engineersdecor/blocks/EdHatchBlock.java b/src/main/java/wile/engineersdecor/blocks/EdHatchBlock.java index ad05d1e..3bf03de 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdHatchBlock.java +++ b/src/main/java/wile/engineersdecor/blocks/EdHatchBlock.java @@ -96,6 +96,10 @@ public class EdHatchBlock extends DecorBlock.HorizontalWaterLoggable implements world.setBlockState(pos, state.with(OPEN, powered).with(POWERED, powered), 1|2); } + @Override + public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) + { return false; } + @Override @SuppressWarnings("deprecation") public void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) diff --git a/src/main/java/wile/engineersdecor/blocks/EdLabeledCrate.java b/src/main/java/wile/engineersdecor/blocks/EdLabeledCrate.java index bf4f2ac..ebbf87d 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdLabeledCrate.java +++ b/src/main/java/wile/engineersdecor/blocks/EdLabeledCrate.java @@ -8,15 +8,11 @@ */ package wile.engineersdecor.blocks; -import wile.engineersdecor.ModContent; -import wile.engineersdecor.ModEngineersDecor; -import wile.engineersdecor.libmc.blocks.StandardBlocks; -import wile.engineersdecor.libmc.client.ContainerGui; -import wile.engineersdecor.libmc.detail.Auxiliaries; -import wile.engineersdecor.libmc.detail.Inventories.InventoryRange; -import wile.engineersdecor.libmc.detail.Networking; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.matrix.MatrixStack; +import javafx.util.Pair; +import net.minecraft.world.IWorldReader; import net.minecraft.world.IBlockReader; -import net.minecraft.world.server.ServerWorld; import net.minecraft.world.World; import net.minecraft.block.material.PushReaction; import net.minecraft.block.Block; @@ -52,15 +48,21 @@ import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fml.network.NetworkHooks; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemHandlerHelper; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.matrix.MatrixStack; +import wile.engineersdecor.ModContent; +import wile.engineersdecor.ModEngineersDecor; +import wile.engineersdecor.libmc.blocks.StandardBlocks; +import wile.engineersdecor.libmc.client.ContainerGui; +import wile.engineersdecor.libmc.detail.Auxiliaries; +import wile.engineersdecor.libmc.detail.Inventories; +import wile.engineersdecor.libmc.detail.Inventories.InventoryRange; +import wile.engineersdecor.libmc.detail.Inventories.StorageInventory; +import wile.engineersdecor.libmc.detail.Inventories.MappedItemHandler; +import wile.engineersdecor.libmc.detail.Networking; -import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; public class EdLabeledCrate @@ -96,6 +98,10 @@ public class EdLabeledCrate public int getComparatorInputOverride(BlockState blockState, World world, BlockPos pos) { return Container.calcRedstone(world.getTileEntity(pos)); } + @Override + public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) + { return false; } + @Override public boolean hasTileEntity(BlockState state) { return true; } @@ -139,7 +145,7 @@ public class EdLabeledCrate Auxiliaries.setItemLabel(stack, ((LabeledCrateTileEntity)te).getCustomName()); stacks.add(stack); } else { - for(ItemStack stack: ((LabeledCrateTileEntity)te).stacks_) stacks.add(stack); + for(ItemStack stack: ((LabeledCrateTileEntity)te).main_inventory_) stacks.add(stack); ((LabeledCrateTileEntity)te).reset_getnbt(); } return stacks; @@ -169,28 +175,40 @@ public class EdLabeledCrate super.addInformation(stack, world, tooltip, flag); return; } - NonNullList items = NonNullList.withSize(LabeledCrateTileEntity.NUM_OF_SLOTS, ItemStack.EMPTY); - int num_used_slots = 0; - int total_items = 0; + ItemStack frameStack = ItemStack.EMPTY; + int num_used_slots = 0, total_items = 0; + String stats = ""; if(stack.hasTag() && stack.getTag().contains("tedata")) { final CompoundNBT nbt = stack.getTag().getCompound("tedata"); if(nbt.contains("Items")) { - ItemStackHelper.loadAllItems(nbt, items); - for(int i=0; i all_items = NonNullList.withSize(LabeledCrateTileEntity.NUM_OF_SLOTS, ItemStack.EMPTY); + ItemStackHelper.loadAllItems(nbt, all_items); + frameStack = all_items.get(LabeledCrateTileEntity.ITEMFRAME_SLOTNO); + all_items.set(LabeledCrateTileEntity.ITEMFRAME_SLOTNO, ItemStack.EMPTY); + Map item_map = new HashMap<>(); + for(ItemStack e:all_items) { // ok, the whole stream map collector seems to be actually slower than a simple loop. + if(!e.isEmpty()) { + item_map.put(e.getItem(), item_map.getOrDefault(e.getItem(), 0) + e.getCount()); + ++num_used_slots; + total_items += e.getCount(); + } } + List> itmes = new ArrayList<>(); + for(Map.Entry e:item_map.entrySet()) itmes.add(new Pair<>(e.getKey().getTranslationKey(), e.getValue())); + itmes.sort((a,b)->b.getValue()-a.getValue()); + boolean dotdotdot = false; + if(itmes.size() > 8) { itmes.subList(8, itmes.size()).clear(); dotdotdot = true; } + stats = itmes.stream().map(e->Auxiliaries.localize(e.getKey())).collect(Collectors.joining(", ")); + if(dotdotdot) stats += "..."; } } int num_free_slots = LabeledCrateTileEntity.ITEMFRAME_SLOTNO - num_used_slots; - ItemStack frameStack = items.get(LabeledCrateTileEntity.ITEMFRAME_SLOTNO); - String[] lines = Auxiliaries.localize(getTranslationKey()+".tip", new Object[] { + String[] lines = Auxiliaries.localize(getTranslationKey()+".tip", new Object[] { (frameStack.isEmpty() ? (new StringTextComponent("-/-")) : (new TranslationTextComponent(frameStack.getTranslationKey()))), num_used_slots, num_free_slots, - total_items + total_items, + stats }).split("\n"); for(String line:lines) { tooltip.add(new StringTextComponent(line.trim())); @@ -202,22 +220,28 @@ public class EdLabeledCrate // Tile entity //-------------------------------------------------------------------------------------------------------------------- - public static class LabeledCrateTileEntity extends TileEntity implements INameable, IInventory, INamedContainerProvider, ISidedInventory + public static class LabeledCrateTileEntity extends TileEntity implements INameable, INamedContainerProvider, Networking.IPacketTileNotifyReceiver { public static final int NUM_OF_FIELDS = 1; public static final int NUM_OF_SLOTS = 55; - public static final int ITEMFRAME_SLOTNO = 54; + public static final int NUM_OF_STORAGE_SLOTS = 54; + public static final int NUM_OF_STORAGE_ROWS = 6; + public static final int ITEMFRAME_SLOTNO = NUM_OF_STORAGE_SLOTS; - // BTileEntity ----------------------------------------------------------------------------- - - protected NonNullList stacks_ = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); + protected final Inventories.StorageInventory main_inventory_ = new StorageInventory(this, NUM_OF_SLOTS, 1); + protected final InventoryRange storage_range_ = new InventoryRange(main_inventory_, 0, NUM_OF_STORAGE_SLOTS, NUM_OF_STORAGE_ROWS); private @Nullable ITextComponent custom_name_; public LabeledCrateTileEntity() { this(ModContent.TET_LABELED_CRATE); } public LabeledCrateTileEntity(TileEntityType te_type) - { super(te_type); reset(); } + { + super(te_type); reset(); + main_inventory_.setCloseAction(player->{ + if(!getWorld().isRemote()) Networking.PacketTileNotifyServerToClient.sendToPlayers(this, writenbt(new CompoundNBT())); + }); + } public CompoundNBT reset_getnbt() { @@ -228,31 +252,34 @@ public class EdLabeledCrate } protected void reset() - { - stacks_ = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); - } + { main_inventory_.clear(); } - public void readnbt(CompoundNBT nbt) + public CompoundNBT readnbt(CompoundNBT nbt) { - NonNullList stacks = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); - if(!nbt.isEmpty()) ItemStackHelper.loadAllItems(nbt, stacks); - while(stacks.size() < NUM_OF_SLOTS) stacks.add(ItemStack.EMPTY); if(nbt.contains("name", NBT.TAG_STRING)) custom_name_ = Auxiliaries.unserializeTextComponent(nbt.getString("name")); - stacks_ = stacks; + main_inventory_.load(nbt); + return nbt; } - protected void writenbt(CompoundNBT nbt) + protected CompoundNBT writenbt(CompoundNBT nbt) { if(custom_name_ != null) nbt.putString("name", Auxiliaries.serializeTextComponent(custom_name_)); - if(!stacks_.stream().allMatch(ItemStack::isEmpty)) ItemStackHelper.saveAllItems(nbt, stacks_); + if(!main_inventory_.isEmpty()) main_inventory_.save(nbt); + return nbt; } public ItemStack getItemFrameStack() - { return (stacks_.size() > ITEMFRAME_SLOTNO) ? (stacks_.get(ITEMFRAME_SLOTNO)) : (ItemStack.EMPTY); } + { return main_inventory_.getStackInSlot(ITEMFRAME_SLOTNO); } protected static boolean inacceptable(ItemStack stack) { return (stack.hasTag() && (!stack.getTag().isEmpty()) && (unstorable_containers.contains(stack.getItem()))); } + // IPacketTileNotifyReceiver --------------------------------------------------------------- + + @Override + public void onServerPacketReceived(CompoundNBT nbt) + { readnbt(nbt); } + // TileEntity ------------------------------------------------------------------------------ @Override @@ -281,11 +308,7 @@ public class EdLabeledCrate @Override public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) // on client - { - //@todo: check if needed: super.read(pkt.getNbtCompound()); - readnbt(pkt.getNbtCompound()); - super.onDataPacket(net, pkt); - } + { readnbt(pkt.getNbtCompound()); super.onDataPacket(net, pkt); } @Override public void handleUpdateTag(BlockState state, CompoundNBT tag) // on client @@ -326,70 +349,7 @@ public class EdLabeledCrate @Override public Container createMenu(int id, PlayerInventory inventory, PlayerEntity player ) - { return new LabeledCrateContainer(id, inventory, this, IWorldPosCallable.of(world, pos), fields); } - - // IInventory ------------------------------------------------------------------------------ - - @Override - public int getSizeInventory() - { return stacks_.size(); } - - @Override - public boolean isEmpty() - { for(ItemStack stack: stacks_) { if(!stack.isEmpty()) return false; } return true; } - - @Override - public ItemStack getStackInSlot(int index) - { return ((index >= 0) && (index < getSizeInventory())) ? stacks_.get(index) : ItemStack.EMPTY; } - - @Override - public ItemStack decrStackSize(int index, int count) - { return ItemStackHelper.getAndSplit(stacks_, index, count); } - - @Override - public ItemStack removeStackFromSlot(int index) - { return ItemStackHelper.getAndRemove(stacks_, index); } - - @Override - public void setInventorySlotContents(int index, ItemStack stack) - { - if(stack.getCount() > getInventoryStackLimit()) stack.setCount(getInventoryStackLimit()); - stacks_.set(index, stack); - markDirty(); - if(getWorld() instanceof ServerWorld) { - // This should result in sending TE data (getUpdateTag etc) to the client for the TER. - BlockState state = world.getBlockState(getPos()); - getWorld().notifyBlockUpdate(getPos(), state, state, 2|16|32); - } - } - - @Override - public int getInventoryStackLimit() - { return 64; } - - @Override - public void markDirty() - { super.markDirty(); } - - @Override - public boolean isUsableByPlayer(PlayerEntity player) - { return ((getWorld().getTileEntity(getPos()) == this)) && (getPos().distanceSq(player.getPosition()) < 64); } - - @Override - public void openInventory(PlayerEntity player) - {} - - @Override - public void closeInventory(PlayerEntity player) - { markDirty(); } - - @Override - public boolean isItemValidForSlot(int index, ItemStack stack) - { return (index != ITEMFRAME_SLOTNO) && (!inacceptable(stack)); } - - @Override - public void clear() - { stacks_.clear(); } + { return new LabeledCrateContainer(id, inventory, main_inventory_, IWorldPosCallable.of(world, pos), fields); } // Fields ----------------------------------------------------------------------------------------------- @@ -411,120 +371,13 @@ public class EdLabeledCrate } }; - // ISidedInventory ---------------------------------------------------------------------------- - - private static final int[] SIDED_INV_SLOTS; - static { - // that useless unoptimised language ... no proper inline conv to int[]? - // private static final int[] SIDED_INV_SLOTS = IntStream.rangeClosed(0, BTileEntity.NUM_OF_SLOTS-2).boxed().collect(Collectors.toList()).toArray(); - SIDED_INV_SLOTS = new int[LabeledCrateTileEntity.NUM_OF_SLOTS-1]; - for(int i=0; i= NUM_OF_SLOTS)) || ((slotno == ITEMFRAME_SLOTNO)) ) return stack; - if((!isItemValid(slotno, stack))) return stack; - ItemStack slotstack = getStackInSlot(slotno); - if(!slotstack.isEmpty()) { - if(slotstack.getCount() >= Math.min(slotstack.getMaxStackSize(), getSlotLimit(slotno))) return stack; - if(!ItemHandlerHelper.canItemStacksStack(stack, slotstack)) return stack; - if(!te.canInsertItem(slotno, stack, Direction.UP) || (!te.isItemValidForSlot(slotno, stack))) return stack; - int n = Math.min(stack.getMaxStackSize(), getSlotLimit(slotno)) - slotstack.getCount(); - if(stack.getCount() <= n) { - if(!simulate) { - ItemStack copy = stack.copy(); - copy.grow(slotstack.getCount()); - te.setInventorySlotContents(slotno, copy); - } - return ItemStack.EMPTY; - } else { - stack = stack.copy(); - if(!simulate) { - ItemStack copy = stack.split(n); - copy.grow(slotstack.getCount()); - te.setInventorySlotContents(slotno, copy); - return stack; - } else { - stack.shrink(n); - return stack; - } - } - } else { - if(!te.canInsertItem(slotno, stack, Direction.UP) || (!te.isItemValidForSlot(slotno, stack))) return stack; - int n = Math.min(stack.getMaxStackSize(), getSlotLimit(slotno)); - if(n < stack.getCount()) { - stack = stack.copy(); - if(!simulate) { - te.setInventorySlotContents(slotno, stack.split(n)); - return stack; - } else { - stack.shrink(n); - return stack; - } - } else { - if(!simulate) te.setInventorySlotContents(slotno, stack); - return ItemStack.EMPTY; - } - } - } - - @Override - @Nonnull - public ItemStack extractItem(int index, int amount, boolean simulate) - { - if((index < 0) || ((index >= NUM_OF_SLOTS)) || ((index == ITEMFRAME_SLOTNO)) ) return ItemStack.EMPTY; - if(!simulate) return ItemStackHelper.getAndSplit(te.stacks_, index, amount); - ItemStack stack = te.stacks_.get(index).copy(); - if(stack.getCount() > amount) stack.setCount(amount); - return stack; - } - - @Override - @Nonnull - public ItemStack getStackInSlot(int index) - { return te.getStackInSlot(index); } - } - // Capability export ---------------------------------------------------------------------------- - protected LazyOptional item_handler_ = LazyOptional.of(() -> new LabeledCrateTileEntity.BItemHandler(this)); + protected LazyOptional item_handler_ = MappedItemHandler.createGenericHandler(storage_range_, + (slot,stack)->(slot!=ITEMFRAME_SLOTNO), + (slot,stack)->(slot!=ITEMFRAME_SLOTNO), + IntStream.range(0, NUM_OF_STORAGE_SLOTS).boxed().collect(Collectors.toList()) + ); @Override public LazyOptional getCapability(net.minecraftforge.common.capabilities.Capability capability, @Nullable Direction facing) @@ -589,6 +442,7 @@ public class EdLabeledCrate player_ = player_inventory.player; inventory_ = block_inventory; wpc_ = wpc; + wpc_.consume((w,p)->inventory_.openInventory(player_)); fields_ = fields; block_storage_range_ = new InventoryRange(inventory_, 0, LabeledCrateTileEntity.ITEMFRAME_SLOTNO); player_inventory_range_ = new InventoryRange(player_inventory, 0, 36); @@ -624,7 +478,10 @@ public class EdLabeledCrate @Override public void onContainerClosed(PlayerEntity player) - { super.onContainerClosed(player); } + { + super.onContainerClosed(player); + inventory_.closeInventory(player); + } @Override public ItemStack transferStackInSlot(PlayerEntity player, int index) diff --git a/src/main/java/wile/engineersdecor/blocks/EdMilker.java b/src/main/java/wile/engineersdecor/blocks/EdMilker.java index c1705dc..1dee13f 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdMilker.java +++ b/src/main/java/wile/engineersdecor/blocks/EdMilker.java @@ -8,13 +8,11 @@ */ package wile.engineersdecor.blocks; -import wile.engineersdecor.libmc.detail.Auxiliaries; -import wile.engineersdecor.libmc.detail.Fluidics; -import wile.engineersdecor.libmc.detail.Inventories; +import net.minecraftforge.common.util.Constants; +import wile.engineersdecor.libmc.detail.*; import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.ModContent; import wile.engineersdecor.detail.ExternalObjects; -import wile.engineersdecor.libmc.detail.Overlay; import net.minecraft.world.World; import net.minecraft.world.IWorldReader; import net.minecraft.world.IBlockReader; @@ -97,6 +95,10 @@ public class EdMilker return (te==null) ? 0 : MathHelper.clamp((16 * te.fluid_level())/MilkerTileEntity.TANK_CAPACITY, 0, 15); } + @Override + public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) + { return false; } + @Override public boolean hasTileEntity(BlockState state) { return true; } @@ -153,7 +155,7 @@ public class EdMilker // Tile entity //-------------------------------------------------------------------------------------------------------------------- - public static class MilkerTileEntity extends TileEntity implements ITickableTileEntity, IEnergyStorage, IFluidTank, ICapabilityProvider + public static class MilkerTileEntity extends TileEntity implements ITickableTileEntity, IFluidTank, ICapabilityProvider { public static final int BUCKET_SIZE = 1000; public static final int TICK_INTERVAL = 80; @@ -171,21 +173,24 @@ public class EdMilker private static FluidStack milk_fluid_ = NO_MILK_FLUID; private static HashMap milk_containers_ = new HashMap<>(); - private static int energy_consumption = DEFAULT_ENERGY_CONSUMPTION; - private static long min_milking_delay_per_cow_ticks = DEFAULT_MILKING_DELAY_PER_COW; + private static int energy_consumption_ = DEFAULT_ENERGY_CONSUMPTION; + private static long min_milking_delay_per_cow_ticks_ = DEFAULT_MILKING_DELAY_PER_COW; private int tick_timer_; - private int energy_stored_; - private int tank_level_ = 0; private UUID tracked_cow_ = null; private MilkingState state_ = MilkingState.IDLE; private int state_timeout_ = 0; private int state_timer_ = 0; private BlockPos tracked_cow_original_position_ = null; + private final RfEnergy.Battery battery_; + private final LazyOptional energy_handler_; + private final Fluidics.Tank tank_; + private final LazyOptional fluid_handler_; + public static void on_config(int energy_consumption_per_tick, int min_milking_delay_per_cow) { - energy_consumption = MathHelper.clamp(energy_consumption_per_tick, 0, 1024); - min_milking_delay_per_cow_ticks = MathHelper.clamp(min_milking_delay_per_cow, 1000, 24000); + energy_consumption_ = MathHelper.clamp(energy_consumption_per_tick, 0, 1024); + min_milking_delay_per_cow_ticks_ = MathHelper.clamp(min_milking_delay_per_cow, 1000, 24000); { ResourceLocation milk_rl = ForgeRegistries.FLUIDS.getKeys().stream().filter(rl->rl.getPath().equals("milk")).findFirst().orElse(null); if(milk_rl != null) { @@ -198,7 +203,7 @@ public class EdMilker if(ExternalObjects.BOTTLED_MILK_BOTTLE_DRINKLABLE!=null) milk_containers_.put(new ItemStack(Items.GLASS_BOTTLE), new ItemStack(ExternalObjects.BOTTLED_MILK_BOTTLE_DRINKLABLE)); } ModEngineersDecor.logger().info( - "Config milker: energy consumption:" + energy_consumption + "rf/t" + "Config milker: energy consumption:" + energy_consumption_ + "rf/t" + ((milk_fluid_==NO_MILK_FLUID)?"":" [milk fluid available]") + ((ExternalObjects.BOTTLED_MILK_BOTTLE_DRINKLABLE==null)?"":" [bottledmilk mod available]") ); @@ -208,12 +213,19 @@ public class EdMilker { this(ModContent.TET_SMALL_MILKING_MACHINE); } public MilkerTileEntity(TileEntityType te_type) - { super(te_type); reset(); } + { + super(te_type); + tank_ = new Fluidics.Tank(TANK_CAPACITY, 0, BUCKET_SIZE, (fs)->(has_milk_fluid() && fs.isFluidEqual(milk_fluid_))); + fluid_handler_ = tank_.createFluidHandler(); + battery_ = new RfEnergy.Battery(MAX_ENERGY_BUFFER, MAX_ENERGY_TRANSFER, 0); + energy_handler_ = battery_.createEnergyHandler(); + reset(); + } public void reset() { - tank_level_ = 0; - energy_stored_ = 0; + tank_.clear(); + battery_.clear(); tick_timer_ = 0; tracked_cow_ = null; state_ = MilkingState.IDLE; @@ -232,29 +244,29 @@ public class EdMilker public void readnbt(CompoundNBT nbt, boolean update_packet) { - tank_level_ = nbt.getInt("tank"); - energy_stored_ = nbt.getInt("energy"); + battery_.load(nbt); + tank_.load(nbt); } protected void writenbt(CompoundNBT nbt, boolean update_packet) { - if(tank_level_ > 0) nbt.putInt("tank", tank_level_); - if(energy_stored_ > 0) nbt.putInt("energy", energy_stored_ ); + tank_.save(nbt); + if(!battery_.isEmpty()) battery_.save(nbt); } private IFluidHandler fluid_handler() { return fluid_handler_.orElse(null); } private int fluid_level() - { return MathHelper.clamp(tank_level_, 0, TANK_CAPACITY); } + { return tank_.getFluidAmount(); } - private void drain(int amount) - { tank_level_ = MathHelper.clamp(tank_level_-BUCKET_SIZE, 0, TANK_CAPACITY); markDirty(); } + private FluidStack drain(int amount) + { return tank_.drain(amount); } public void state_message(PlayerEntity player) { - ITextComponent rf = (energy_consumption <= 0) ? (new StringTextComponent("")) : (Auxiliaries.localizable("block.engineersdecor.small_milking_machine.status.rf", new Object[]{energy_stored_})); - Overlay.show(player, Auxiliaries.localizable("block.engineersdecor.small_milking_machine.status", new Object[]{tank_level_, rf})); + ITextComponent rf = (energy_consumption_ <= 0) ? (new StringTextComponent("")) : (Auxiliaries.localizable("block.engineersdecor.small_milking_machine.status.rf", new Object[]{battery_.getEnergyStored()})); + Overlay.show(player, Auxiliaries.localizable("block.engineersdecor.small_milking_machine.status", new Object[]{tank_.getFluidAmount(), rf})); } // TileEntity ------------------------------------------------------------------------------ @@ -275,30 +287,6 @@ public class EdMilker fluid_handler_.invalidate(); } - // IEnergyStorage ---------------------------------------------------------------------------- - - protected LazyOptional energy_handler_ = LazyOptional.of(() -> (IEnergyStorage)this); - - @Override public boolean canExtract() { return false; } - @Override public boolean canReceive() { return true; } - @Override public int getMaxEnergyStored() { return MAX_ENERGY_BUFFER; } - @Override public int getEnergyStored() { return energy_stored_; } - @Override public int extractEnergy(int maxExtract, boolean simulate) { return 0; } - - @Override - public int receiveEnergy(int maxReceive, boolean simulate) - { - if(energy_stored_ >= MAX_ENERGY_BUFFER) return 0; - int n = Math.min(maxReceive, (MAX_ENERGY_BUFFER - energy_stored_)); - if(n > MAX_ENERGY_TRANSFER) n = MAX_ENERGY_TRANSFER; - if(!simulate) {energy_stored_ += n; markDirty(); } - return n; - } - - // IFluidHandler --------------------------------------------------------------------------------------- - - private LazyOptional fluid_handler_ = LazyOptional.of(() -> (IFluidHandler)new Fluidics.SingleTankFluidHandler(this)); - // IFluidTank ------------------------------------------------------------------------------------------ private boolean has_milk_fluid() @@ -335,10 +323,7 @@ public class EdMilker public FluidStack drain(int maxDrain, FluidAction action) { if((!has_milk_fluid()) || (fluid_level() <= 0)) return FluidStack.EMPTY; - FluidStack fs = milk_fluid_.copy(); - fs.setAmount(Math.min(fs.getAmount(), fluid_level())); - if(action==FluidAction.EXECUTE) tank_level_ -= fs.getAmount(); - return fs; + return tank_.drain(maxDrain, action); } // ICapabilityProvider --------------------------------------------------------------------------- @@ -347,7 +332,7 @@ public class EdMilker public LazyOptional getCapability(net.minecraftforge.common.capabilities.Capability capability, @Nullable Direction facing) { if((capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) && has_milk_fluid()) return fluid_handler_.cast(); - if((capability == CapabilityEnergy.ENERGY) && (energy_consumption>0)) return energy_handler_.cast(); + if((capability == CapabilityEnergy.ENERGY) && (energy_consumption_>0)) return energy_handler_.cast(); return super.getCapability(capability, facing); } @@ -369,13 +354,13 @@ public class EdMilker if(src==null) { src = dst; } else if(dst==null) { dst = src; } if((src==null) || (dst==null)) return false; boolean dirty = false; - while((tank_level_ >= BUCKET_SIZE)) { + while((tank_.getFluidAmount() >= BUCKET_SIZE)) { boolean inserted = false; for(Entry e:milk_containers_.entrySet()) { if(Inventories.extract(src, e.getKey(), 1, true).isEmpty()) continue; if(!Inventories.insert(dst, e.getValue().copy(), false).isEmpty()) continue; Inventories.extract(src, e.getKey(), 1, false); - tank_level_ -= BUCKET_SIZE; + tank_.drain(BUCKET_SIZE); inserted = true; dirty = true; break; @@ -392,7 +377,7 @@ public class EdMilker for(Direction dir:Direction.values()) { int amount = Fluidics.fill(getWorld(), getPos().offset(dir), dir.getOpposite(), fs); if(amount > 0) { - tank_level_ = Math.max(fluid_level() - amount, 0); + tank_.drain(amount); return true; } } @@ -429,7 +414,7 @@ public class EdMilker if(e.getUniqueID().equals(tracked_cow_)) return true; if((tracked_cow_!=null) || e.isChild() || e.isInLove() || e.isBeingRidden()) return false; if(!e.getNavigator().noPath()) return false; - if(Math.abs(tracked_cows_.getOrDefault(e.getEntityId(), 0L)-t) < min_milking_delay_per_cow_ticks) return false; + if(Math.abs(tracked_cows_.getOrDefault(e.getEntityId(), 0L)-t) < min_milking_delay_per_cow_ticks_) return false; return true; } ); @@ -512,7 +497,7 @@ public class EdMilker return false; } case MILKING: { - tank_level_ = MathHelper.clamp(tank_level_+BUCKET_SIZE, 0, TANK_CAPACITY); + tank_.fill(milk_fluid_.copy(), FluidAction.EXECUTE); state_timeout_ = 600; state_ = MilkingState.LEAVING; state_timer_ = 20; @@ -558,24 +543,19 @@ public class EdMilker final BlockState block_state = world.getBlockState(pos); if(!(block_state.getBlock() instanceof MilkerBlock)) return; if(!world.isBlockPowered(pos) || (state_ != MilkingState.IDLE)) { - if(energy_consumption > 0) { - if(energy_stored_ <= 0) return; - energy_stored_ = MathHelper.clamp(energy_stored_-energy_consumption, 0, MAX_ENERGY_BUFFER); - } + if((energy_consumption_ > 0) && (!battery_.draw(energy_consumption_))) return; // Track and milk cows if(milking_process()) dirty = true; // Fluid transfer - if((milk_fluid_.getAmount() > 0) && (fluid_level() >= BUCKET_SIZE)) { + if(has_milk_fluid() && (!tank_.isEmpty())) { log("Fluid transfer"); for(Direction facing: FLUID_TRANSFER_DIRECTRIONS) { - IFluidHandler fh = FluidUtil.getFluidHandler(world, pos.offset(facing), facing.getOpposite()).orElse(null); + final IFluidHandler fh = FluidUtil.getFluidHandler(world, pos.offset(facing), facing.getOpposite()).orElse(null); if(fh == null) continue; - FluidStack fs = milk_fluid_.copy(); - fs.setAmount(BUCKET_SIZE); - int nfilled = MathHelper.clamp(fh.fill(fs, FluidAction.EXECUTE), 0, BUCKET_SIZE); + final FluidStack fs = tank_.drain(BUCKET_SIZE, FluidAction.SIMULATE); + int nfilled = fh.fill(fs, FluidAction.EXECUTE); if(nfilled <= 0) continue; - tank_level_ -= nfilled; - if(tank_level_ < 0) tank_level_ = 0; + tank_.drain(nfilled, FluidAction.EXECUTE); dirty = true; break; } diff --git a/src/main/java/wile/engineersdecor/blocks/EdMineralSmelter.java b/src/main/java/wile/engineersdecor/blocks/EdMineralSmelter.java index 10ef605..2a99caf 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdMineralSmelter.java +++ b/src/main/java/wile/engineersdecor/blocks/EdMineralSmelter.java @@ -9,6 +9,7 @@ */ package wile.engineersdecor.blocks; +import net.minecraft.world.IWorldReader; import wile.engineersdecor.ModContent; import wile.engineersdecor.ModEngineersDecor; import net.minecraft.world.IBlockReader; @@ -85,6 +86,10 @@ public class EdMineralSmelter public int getComparatorInputOverride(BlockState state, World world, BlockPos pos) { return MathHelper.clamp((state.get(PHASE)*5), 0, 15); } + @Override + public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) + { return false; } + @Override public boolean hasTileEntity(BlockState state) { return true; } diff --git a/src/main/java/wile/engineersdecor/blocks/EdPipeValve.java b/src/main/java/wile/engineersdecor/blocks/EdPipeValve.java index d6bca1f..6977c49 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdPipeValve.java +++ b/src/main/java/wile/engineersdecor/blocks/EdPipeValve.java @@ -9,6 +9,7 @@ */ package wile.engineersdecor.blocks; +import net.minecraft.world.IWorldReader; import wile.engineersdecor.ModContent; import wile.engineersdecor.ModEngineersDecor; import net.minecraft.world.IWorld; @@ -143,6 +144,10 @@ public class EdPipeValve public boolean canConnectRedstone(BlockState state, IBlockReader world, BlockPos pos, @Nullable Direction side) { return (side!=null) && (side!=state.get(FACING)) && (side!=state.get(FACING).getOpposite()); } + @Override + public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) + { return false; } + @Override @SuppressWarnings("deprecation") public boolean canProvidePower(BlockState state) diff --git a/src/main/java/wile/engineersdecor/blocks/EdPlacer.java b/src/main/java/wile/engineersdecor/blocks/EdPlacer.java index 53c4bf3..0fd2c47 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdPlacer.java +++ b/src/main/java/wile/engineersdecor/blocks/EdPlacer.java @@ -13,6 +13,7 @@ import net.minecraft.inventory.container.ClickType; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.block.*; import net.minecraft.world.IBlockReader; +import net.minecraft.world.IWorldReader; import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; import net.minecraft.tileentity.ITickableTileEntity; @@ -89,6 +90,10 @@ public class EdPlacer public int getComparatorInputOverride(BlockState blockState, World world, BlockPos pos) { return Container.calcRedstone(world.getTileEntity(pos)); } + @Override + public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) + { return false; } + @Override public boolean hasTileEntity(BlockState state) { return true; } diff --git a/src/main/java/wile/engineersdecor/blocks/EdSolarPanel.java b/src/main/java/wile/engineersdecor/blocks/EdSolarPanel.java index efc195d..d7431fa 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdSolarPanel.java +++ b/src/main/java/wile/engineersdecor/blocks/EdSolarPanel.java @@ -8,6 +8,7 @@ */ package wile.engineersdecor.blocks; +import net.minecraft.world.IWorldReader; import wile.engineersdecor.ModContent; import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.libmc.detail.Auxiliaries; @@ -77,6 +78,10 @@ public class EdSolarPanel if(te instanceof SolarPanelTileEntity) ((SolarPanelTileEntity)te).state_message(player); return ActionResultType.CONSUME; } + + @Override + public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) + { return false; } } //-------------------------------------------------------------------------------------------------------------------- diff --git a/src/main/java/wile/engineersdecor/blocks/EdTreeCutter.java b/src/main/java/wile/engineersdecor/blocks/EdTreeCutter.java index b3eb930..c30e9b8 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdTreeCutter.java +++ b/src/main/java/wile/engineersdecor/blocks/EdTreeCutter.java @@ -8,6 +8,7 @@ */ package wile.engineersdecor.blocks; +import net.minecraft.world.IWorldReader; import wile.engineersdecor.ModContent; import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.detail.TreeCutting; @@ -95,6 +96,10 @@ public class EdTreeCutter if(te instanceof TreeCutterTileEntity) ((TreeCutterTileEntity)te).state_message(player); return ActionResultType.CONSUME; } + + @Override + public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) + { return false; } } //-------------------------------------------------------------------------------------------------------------------- diff --git a/src/main/java/wile/engineersdecor/blocks/EdWasteIncinerator.java b/src/main/java/wile/engineersdecor/blocks/EdWasteIncinerator.java index 7f1c052..9051b9a 100644 --- a/src/main/java/wile/engineersdecor/blocks/EdWasteIncinerator.java +++ b/src/main/java/wile/engineersdecor/blocks/EdWasteIncinerator.java @@ -23,6 +23,7 @@ import net.minecraft.util.text.StringTextComponent; import net.minecraft.world.IBlockReader; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.world.IWorldReader; import net.minecraft.world.World; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; @@ -93,6 +94,10 @@ public class EdWasteIncinerator public int getComparatorInputOverride(BlockState blockState, World world, BlockPos pos) { return Container.calcRedstone(world.getTileEntity(pos)); } + @Override + public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) + { return false; } + @Override public boolean hasTileEntity(BlockState state) { return true; } diff --git a/src/main/java/wile/engineersdecor/detail/ModRenderers.java b/src/main/java/wile/engineersdecor/detail/ModRenderers.java index d8e4b96..52c8897 100644 --- a/src/main/java/wile/engineersdecor/detail/ModRenderers.java +++ b/src/main/java/wile/engineersdecor/detail/ModRenderers.java @@ -150,14 +150,10 @@ public class ModRenderers double ox = tr[di][0], oy = tr[di][1], oz = tr[di][2]; float ry = (float)tr[di][3]; mxs.push(); - //GlStateManager.disableLighting(); - //RenderHelper.enableStandardItemLighting(); mxs.translate(0.5+ox, 0.5+oy, 0.5+oz); mxs.rotate(Vector3f.YP.rotationDegrees(ry)); mxs.scale(scaler, scaler, scaler); Minecraft.getInstance().getItemRenderer().renderItem(stack, net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType.FIXED, i5, i6, mxs, buf); - //RenderHelper.disableStandardItemLighting(); - //GlStateManager.enableLighting(); mxs.pop(); } catch(Throwable e) { if(--tesr_error_counter<=0) { diff --git a/src/main/java/wile/engineersdecor/libmc/detail/Auxiliaries.java b/src/main/java/wile/engineersdecor/libmc/detail/Auxiliaries.java index 086b21f..a8a204c 100644 --- a/src/main/java/wile/engineersdecor/libmc/detail/Auxiliaries.java +++ b/src/main/java/wile/engineersdecor/libmc/detail/Auxiliaries.java @@ -151,7 +151,7 @@ public class Auxiliaries if(!r) m = ""; } } - mt.appendReplacement(sb, (new TranslationTextComponent(m)).getString().trim()); + mt.appendReplacement(sb, Matcher.quoteReplacement((new TranslationTextComponent(m)).getString().trim())); } mt.appendTail(sb); return sb.toString(); diff --git a/src/main/java/wile/engineersdecor/libmc/detail/Fluidics.java b/src/main/java/wile/engineersdecor/libmc/detail/Fluidics.java index f79375f..75d5893 100644 --- a/src/main/java/wile/engineersdecor/libmc/detail/Fluidics.java +++ b/src/main/java/wile/engineersdecor/libmc/detail/Fluidics.java @@ -16,9 +16,11 @@ import net.minecraft.util.Direction; import net.minecraft.util.Hand; import net.minecraft.util.Tuple; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.FluidActionResult; import net.minecraftforge.fluids.FluidStack; @@ -56,6 +58,19 @@ public class Fluidics @Override public FluidStack drain(int maxDrain, FluidAction action) { return tank_.drain(maxDrain, action); } } + private static class SingleTankOutputFluidHandler implements IFluidHandler + { + private final IFluidTank tank_; + public SingleTankOutputFluidHandler(IFluidTank tank) { tank_ = tank; } + @Override public int getTanks() { return 1; } + @Override public FluidStack getFluidInTank(int tank) { return tank_.getFluid().copy(); } + @Override public int getTankCapacity(int tank) { return tank_.getCapacity(); } + @Override public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { return true; } + @Override public int fill(FluidStack resource, FluidAction action) { return 0; } + @Override public FluidStack drain(FluidStack resource, FluidAction action) { return tank_.drain(resource, action); } + @Override public FluidStack drain(int maxDrain, FluidAction action) { return tank_.drain(maxDrain, action); } + } + /** * Simple fluid tank, validator concept according to reference implementation by KingLemming. */ @@ -65,24 +80,41 @@ public class Fluidics private BiConsumer interaction_notifier_ = ((tank,diff)->{}); private FluidStack fluid_ = FluidStack.EMPTY; private int capacity_; + private int fill_rate_; + private int drain_rate_; public Tank(int capacity) - { capacity_ = capacity; } + { this(capacity, capacity, capacity); } - public Tank(int capacity, Predicate validator) - { capacity_ = capacity; setValidator(validator); } + public Tank(int capacity, int fill_rate, int drain_rate) + { this(capacity, fill_rate, drain_rate, e->true); } - public Tank readnbt(CompoundNBT nbt) - { setFluid(FluidStack.loadFluidStackFromNBT(nbt)); return this; } + public Tank(int capacity, int fill_rate, int drain_rate, Predicate validator) + { + capacity_ = capacity; + setMaxFillRate(fill_rate); + setMaxDrainRate(drain_rate); + setValidator(validator); + } - public CompoundNBT writenbt() - { return writenbt(new CompoundNBT()); } + public Tank load(CompoundNBT nbt) + { + if(nbt.contains("tank", Constants.NBT.TAG_COMPOUND)) { + setFluid(FluidStack.loadFluidStackFromNBT(nbt.getCompound("tank"))); + } else { + clear(); + } + return this; + } - public CompoundNBT writenbt(CompoundNBT nbt) - { fluid_.writeToNBT(nbt); return nbt; } + public CompoundNBT save(CompoundNBT nbt) + { if(!isEmpty()) { nbt.put("tank", fluid_.writeToNBT(new CompoundNBT())); } return nbt; } public void reset() - { setFluid(null); } + { clear(); } + + public Tank clear() + { setFluid(null); return this; } public int getCapacity() { return capacity_; } @@ -90,12 +122,32 @@ public class Fluidics public Tank setCapacity(int capacity) { capacity_ = capacity; return this; } + public int getMaxDrainRate() + { return drain_rate_; } + + public Tank setMaxDrainRate(int rate) + { drain_rate_ = MathHelper.clamp(rate, 0, capacity_); return this; } + + public int getMaxFillRate() + { return fill_rate_; } + + public Tank setMaxFillRate(int rate) + { fill_rate_ = MathHelper.clamp(rate, 0, capacity_); return this; } + public Tank setValidator(Predicate validator) { validator_ = (validator!=null) ? validator : ((e)->true); return this; } public Tank setInteractionNotifier(BiConsumer notifier) { interaction_notifier_ = (notifier!=null) ? notifier : ((tank,diff)->{}); return this; } + public LazyOptional createFluidHandler() + { return LazyOptional.of(() -> new Fluidics.SingleTankFluidHandler(this)); } + + public LazyOptional createOutputFluidHandler() + { return LazyOptional.of(() -> new Fluidics.SingleTankOutputFluidHandler(this)); } + + // IFluidTank ------------------------------------------------------------------------------------ + @Nonnull public FluidStack getFluid() { return fluid_; } @@ -109,13 +161,19 @@ public class Fluidics public boolean isEmpty() { return fluid_.isEmpty(); } + public boolean isFull() + { return getFluidAmount() >= getCapacity(); } + public boolean isFluidValid(FluidStack stack) { return validator_.test(stack); } + public boolean isFluidEqual(FluidStack stack) + { return (stack==null) ? (fluid_.isEmpty()) : fluid_.isFluidEqual(stack); } + @Override public int fill(FluidStack fs, FluidAction action) { - if(fs.isEmpty() || (!isFluidValid(fs))) { + if((fs==null) || fs.isEmpty() || (!isFluidValid(fs))) { return 0; } else if(action.simulate()) { if(fluid_.isEmpty()) return Math.min(capacity_, fs.getAmount()); diff --git a/src/main/java/wile/engineersdecor/libmc/detail/Inventories.java b/src/main/java/wile/engineersdecor/libmc/detail/Inventories.java index 7166c77..02e3785 100644 --- a/src/main/java/wile/engineersdecor/libmc/detail/Inventories.java +++ b/src/main/java/wile/engineersdecor/libmc/detail/Inventories.java @@ -23,16 +23,20 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.ISidedInventory; +import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.wrapper.InvWrapper; import net.minecraftforge.items.wrapper.SidedInvWrapper; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.*; import java.util.function.BiPredicate; import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.IntStream; import java.util.stream.Stream; @@ -116,6 +120,169 @@ public class Inventories return remaining; } + //-------------------------------------------------------------------------------------------------------------------- + + public static class MappedItemHandler implements IItemHandler + { + private BiPredicate extraction_predicate_; + private BiPredicate insertion_predicate_; + private List slot_map_; + private final IInventory inv_; + + public MappedItemHandler(IInventory inv, List slot_map, BiPredicate extraction_predicate, BiPredicate insertion_predicate) + { inv_ = inv; extraction_predicate_ = extraction_predicate; insertion_predicate_ = insertion_predicate; slot_map_ = slot_map; } + + public MappedItemHandler(IInventory inv, BiPredicate extraction_predicate, BiPredicate insertion_predicate) + { this(inv, IntStream.range(0, inv.getSizeInventory()).boxed().collect(Collectors.toList()), extraction_predicate, insertion_predicate); } + + public MappedItemHandler(IInventory inv) + { this(inv, (i,s)->true, (i,s)->true); } + + @Override + public int hashCode() + { return inv_.hashCode(); } + + @Override + public boolean equals(Object o) + { return (o==this) || ((o!=null) && (getClass()==o.getClass()) && (inv_.equals(((MappedItemHandler)o).inv_))); } + + // IItemHandler ----------------------------------------------------------------------------------------------- + + @Override + public int getSlots() + { return slot_map_.size(); } + + @Override + @Nonnull + public ItemStack getStackInSlot(int slot) + { return (slot >= slot_map_.size()) ? ItemStack.EMPTY : inv_.getStackInSlot(slot_map_.get(slot)); } + + @Override + public int getSlotLimit(int slot) + { return inv_.getInventoryStackLimit(); } + + @Override + public boolean isItemValid(int slot, @Nonnull ItemStack stack) + { + if(slot >= slot_map_.size()) return false; + slot = slot_map_.get(slot); + return insertion_predicate_.test(slot, stack) && inv_.isItemValidForSlot(slot, stack); + } + + @Override + @Nonnull + public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) + { + if(stack.isEmpty()) return ItemStack.EMPTY; + if(slot >= slot_map_.size()) return stack; + slot = slot_map_.get(slot); + if(!insertion_predicate_.test(slot, stack)) return stack; + if(!inv_.isItemValidForSlot(slot, stack)) return stack; + ItemStack sst = inv_.getStackInSlot(slot); + final int slot_limit = inv_.getInventoryStackLimit(); + if(!sst.isEmpty()) { + if(sst.getCount() >= Math.min(sst.getMaxStackSize(), slot_limit)) return stack; + if(!ItemHandlerHelper.canItemStacksStack(stack, sst)) return stack; + final int limit = Math.min(stack.getMaxStackSize(), slot_limit) - sst.getCount(); + if(stack.getCount() <= limit) { + if(!simulate) { + stack = stack.copy(); + stack.grow(sst.getCount()); + inv_.setInventorySlotContents(slot, stack); + inv_.markDirty(); + } + return ItemStack.EMPTY; + } else { + stack = stack.copy(); + if(simulate) { + stack.shrink(limit); + } else { + ItemStack diff = stack.split(limit); + diff.grow(sst.getCount()); + inv_.setInventorySlotContents(slot, diff); + inv_.markDirty(); + } + return stack; + } + } else { + final int limit = Math.min(slot_limit, stack.getMaxStackSize()); + if(stack.getCount() >= limit) { + stack = stack.copy(); + if(simulate) { + stack.shrink(limit); + } else { + inv_.setInventorySlotContents(slot, stack.split(limit)); + inv_.markDirty(); + } + return stack; + } else { + if(!simulate) { + inv_.setInventorySlotContents(slot, stack.copy()); + inv_.markDirty(); + } + return ItemStack.EMPTY; + } + } + } + + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) + { + if(amount <= 0) return ItemStack.EMPTY; + if(slot >= slot_map_.size()) return ItemStack.EMPTY; + slot = slot_map_.get(slot); + ItemStack stack = inv_.getStackInSlot(slot); + if(!extraction_predicate_.test(slot, stack)) return ItemStack.EMPTY; + if(simulate) { + stack = stack.copy(); + if(amount < stack.getCount()) stack.setCount(amount); + } else { + stack = inv_.decrStackSize(slot, Math.min(stack.getCount(), amount)); + inv_.markDirty(); + } + return stack; + } + + // Factories -------------------------------------------------------------------------------------------- + + public static LazyOptional createGenericHandler(IInventory inv, BiPredicate extraction_predicate, BiPredicate insertion_predicate, List slot_map) + { return LazyOptional.of(() -> new MappedItemHandler(inv, slot_map, extraction_predicate, insertion_predicate)); } + + public static LazyOptional createGenericHandler(IInventory inv, BiPredicate extraction_predicate, BiPredicate insertion_predicate) + { return LazyOptional.of(() -> new MappedItemHandler(inv, extraction_predicate, insertion_predicate)); } + + public static LazyOptional createGenericHandler(IInventory inv) + { return LazyOptional.of(() -> new MappedItemHandler(inv)); } + + + public static LazyOptional createExtractionHandler(IInventory inv, BiPredicate extraction_predicate, List slot_map) + { return LazyOptional.of(() -> new MappedItemHandler(inv, slot_map, extraction_predicate, (i, s)->false)); } + + public static LazyOptional createExtractionHandler(IInventory inv, BiPredicate extraction_predicate) + { return LazyOptional.of(() -> new MappedItemHandler(inv, extraction_predicate, (i, s)->false)); } + + public static LazyOptional createExtractionHandler(IInventory inv, Integer... slots) + { return LazyOptional.of(() -> new MappedItemHandler(inv, Arrays.asList(slots), (i, s)->true, (i, s)->false)); } + + public static LazyOptional createExtractionHandler(IInventory inv) + { return LazyOptional.of(() -> new MappedItemHandler(inv, (i, s)->true, (i, s)->false)); } + + + public static LazyOptional createInsertionHandler(IInventory inv, BiPredicate insertion_predicate, List slot_map) + { return LazyOptional.of(() -> new MappedItemHandler(inv, slot_map, (i, s)->false, insertion_predicate)); } + + public static LazyOptional createInsertionHandler(IInventory inv, Integer... slots) + { return LazyOptional.of(() -> new MappedItemHandler(inv, Arrays.asList(slots), (i, s)->false, (i, s)->true)); } + + public static LazyOptional createInsertionHandler(IInventory inv, BiPredicate insertion_predicate) + { return LazyOptional.of(() -> new MappedItemHandler(inv, (i, s)->false, insertion_predicate)); } + + public static LazyOptional createInsertionHandler(IInventory inv) + { return LazyOptional.of(() -> new MappedItemHandler(inv, (i, s)->false, (i, s)->true)); } + } + + //-------------------------------------------------------------------------------------------------------------------- + public static class InventoryRange implements IInventory, Iterable { public final IInventory inventory; @@ -385,6 +552,9 @@ public class Inventories return changed; } + public boolean move(final InventoryRange target_range, boolean only_fillup) + { return move(target_range, only_fillup, false, true); } + public boolean move(final InventoryRange target_range) { return move(target_range, false, false, true); } @@ -428,6 +598,9 @@ public class Inventories protected Consumer open_action_ = (player)->{}; protected Consumer close_action_ = (player)->{}; + public StorageInventory(TileEntity te, int size) + { this(te, size, 1); } + public StorageInventory(TileEntity te, int size, int num_rows) { te_ = te; @@ -442,16 +615,22 @@ public class Inventories public CompoundNBT save(CompoundNBT nbt, boolean save_empty) { return ItemStackHelper.saveAllItems(nbt, stacks_, save_empty); } + public CompoundNBT save(boolean save_empty) + { return save(new CompoundNBT(), save_empty); } + public StorageInventory load(CompoundNBT nbt) { + stacks_.clear(); ItemStackHelper.loadAllItems(nbt, stacks_); - while(stacks_.size() < size_) stacks_.add(ItemStack.EMPTY); return this; } public NonNullList stacks() { return stacks_; } + public TileEntity getTileEntity() + { return te_; } + public StorageInventory setOpenAction(Consumer fn) { open_action_ = fn; return this; } @@ -461,6 +640,9 @@ public class Inventories public StorageInventory setStackLimit(int max_slot_stack_size) { stack_limit_ = Math.max(max_slot_stack_size, 1); return this; } + public StorageInventory setValidator(BiPredicate validator) + { validator_ = validator; return this; } + // Iterable --------------------------------------------------------------------- public Iterator iterator() @@ -521,7 +703,7 @@ public class Inventories @Override public void clear() - { stacks_.clear(); } + { stacks_.clear(); markDirty(); } } @@ -541,6 +723,13 @@ public class Inventories //-------------------------------------------------------------------------------------------------------------------- + public static IInventory readNbtStacks(CompoundNBT nbt, String key, IInventory target) + { + NonNullList stacks = Inventories.readNbtStacks(nbt, key, target.getSizeInventory()); + for(int i=0; i readNbtStacks(CompoundNBT nbt, String key, int size) { NonNullList stacks = NonNullList.withSize(size, ItemStack.EMPTY); diff --git a/src/main/java/wile/engineersdecor/libmc/detail/Networking.java b/src/main/java/wile/engineersdecor/libmc/detail/Networking.java index a60ce6f..e51b96e 100644 --- a/src/main/java/wile/engineersdecor/libmc/detail/Networking.java +++ b/src/main/java/wile/engineersdecor/libmc/detail/Networking.java @@ -111,6 +111,12 @@ public class Networking DEFAULT_CHANNEL.sendTo(new PacketTileNotifyServerToClient(te, nbt), ((ServerPlayerEntity)player).connection.netManager, NetworkDirection.PLAY_TO_CLIENT); } + public static void sendToPlayers(TileEntity te, CompoundNBT nbt) + { + if(te==null) return; + for(PlayerEntity player: te.getWorld().getPlayers()) sendToPlayer(player, te, nbt); + } + public PacketTileNotifyServerToClient() {} diff --git a/src/main/java/wile/engineersdecor/libmc/detail/RfEnergy.java b/src/main/java/wile/engineersdecor/libmc/detail/RfEnergy.java new file mode 100644 index 0000000..42e9216 --- /dev/null +++ b/src/main/java/wile/engineersdecor/libmc/detail/RfEnergy.java @@ -0,0 +1,142 @@ +/* + * @file RfEnergy.java + * @author Stefan Wilhelm (wile) + * @copyright (C) 2020 Stefan Wilhelm + * @license MIT (see https://opensource.org/licenses/MIT) + * + * General RF/FE energy handling functionality. + */ +package wile.engineersdecor.libmc.detail; + +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.math.MathHelper; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.energy.IEnergyStorage; + +public class RfEnergy +{ + public static class Battery implements IEnergyStorage + { + protected int capacity_; + protected int charge_rate_; + protected int discharge_rate_; + protected int energy_; + + public Battery(int capacity) + { this(capacity, capacity); } + + public Battery(int capacity, int transfer_rate) + { this(capacity, transfer_rate, transfer_rate, 0); } + + public Battery(int capacity, int charge_rate, int discharge_rate) + { this(capacity, charge_rate, discharge_rate, 0); } + + public Battery(int capacity, int charge_rate, int discharge_rate, int energy) + { + capacity_ = Math.max(capacity, 1); + charge_rate_ = MathHelper.clamp(charge_rate, 0, capacity_); + discharge_rate_ = MathHelper.clamp(discharge_rate, 0, capacity_); + energy_ = MathHelper.clamp(energy, 0, capacity_); + } + + // --------------------------------------------------------------------------------------------------- + + public Battery setMaxEnergyStored(int capacity) + { capacity_ = Math.max(capacity, 1); return this; } + + public Battery setEnergyStored(int energy) + { energy_ = MathHelper.clamp(energy, 0, capacity_); return this; } + + public Battery setChargeRate(int in_rate) + { charge_rate_ = MathHelper.clamp(in_rate, 0, capacity_); return this; } + + public Battery setDischargeRate(int out_rate) + { discharge_rate_ = MathHelper.clamp(out_rate, 0, capacity_); return this; } + + public int getChargeRate() + { return charge_rate_; } + + public int getDischargeRate() + { return discharge_rate_; } + + public boolean isEmpty() + { return energy_ <= 0; } + + public boolean isFull() + { return energy_ >= capacity_; } + + public int getSOC() + { return (int)MathHelper.clamp((100.0 * energy_ / capacity_ + .5), 0, 100); } + + public int getComparatorOutput() + { return (int)MathHelper.clamp((15.0 * energy_ / capacity_ + .2), 0, 15); } + + public boolean draw(int energy) + { + if(energy_ < energy) return false; + energy_ -= energy; + return true; + } + + public boolean feed(int energy) + { + energy_ = Math.min(energy_+energy, capacity_); + return energy_ >= capacity_; + } + + public Battery clear() + { energy_ = 0; return this; } + + public Battery load(CompoundNBT nbt, String key) + { setEnergyStored(nbt.getInt(key)); return this; } + + public Battery load(CompoundNBT nbt) + { return load(nbt, "Energy"); } + + public CompoundNBT save(CompoundNBT nbt, String key) + { nbt.putInt(key, energy_); return nbt; } + + public CompoundNBT save(CompoundNBT nbt) + { return save(nbt, "Energy"); } + + public LazyOptional createEnergyHandler() + { return LazyOptional.of(() -> (IEnergyStorage)this); } + + // IEnergyStorage ------------------------------------------------------------------------------------ + + @Override + public int receiveEnergy(int feed_energy, boolean simulate) + { + if(!canReceive()) return 0; + int e = Math.min(Math.min(charge_rate_, feed_energy), capacity_-energy_); + if(!simulate) energy_ += e; + return e; + } + + @Override + public int extractEnergy(int draw_energy, boolean simulate) + { + if(!canExtract()) return 0; + int e = Math.min(Math.min(discharge_rate_, draw_energy), energy_); + if(!simulate) energy_ -= e; + return e; + } + + @Override + public int getEnergyStored() + { return energy_; } + + @Override + public int getMaxEnergyStored() + { return capacity_; } + + @Override + public boolean canExtract() + { return discharge_rate_ > 0; } + + @Override + public boolean canReceive() + { return charge_rate_ > 0; } + + } +} diff --git a/src/main/resources/assets/engineersdecor/lang/en_us.json b/src/main/resources/assets/engineersdecor/lang/en_us.json index 1746eed..442dab3 100644 --- a/src/main/resources/assets/engineersdecor/lang/en_us.json +++ b/src/main/resources/assets/engineersdecor/lang/en_us.json @@ -140,12 +140,12 @@ "block.engineersdecor.iron_floor_edge_light": "Inset Floor Edge Light", "block.engineersdecor.iron_floor_edge_light.help": "Small glowstone light source,\n placed at the edge of a floor\n block. Useful to light up places\n where electrical light\n installations are problematic.", "block.engineersdecor.iron_hatch": "Iron Hatch", - "block.engineersdecor.iron_hatch.help": "An upside down trapdoor, placed\n above mainenance shafts or ladders.\n Creeper-proof, works as ladder\n when open.", + "block.engineersdecor.iron_hatch.help": "An upside down trapdoor, placed\n above maintenance shafts or ladders.\n Creeper-proof, works as ladder\n when open.", "block.engineersdecor.iron_inset_light": "Inset Light", "block.engineersdecor.iron_inset_light.help": "Small glowstone light source, sunk\n into the floor, ceiling or wall.\n Useful to light up places where\n electrical light installations\n are problematic.", "block.engineersdecor.labeled_crate": "Labeled Crate", "block.engineersdecor.labeled_crate.help": "A storage crate with 9x6 slots and\n a built-in item frame at the front.\n Place an item into the frame slot\n at the bottom right of the GUI to\n define the shown label.", - "block.engineersdecor.labeled_crate.tip": "§6Label:§r %1$s\n%2$s slots used / %3$s free\n%4$s total items stored", + "block.engineersdecor.labeled_crate.tip": "§6Label:§r %1$s\n%2$s slots used / %3$s free\n%4$s total items stored\n---\n%5$s", "block.engineersdecor.metal_crafting_table": "Metal Crafting Table", "block.engineersdecor.metal_crafting_table.help": "Decorative crafting table with\n advanced features. Eighteen storage\n slots, keeps inventory, no vanilla\n recipe book. Click up/down arrow\n buttons for crafting history\n selection, output slot for item\n placement, X-button to clear\n crafting grid and history.\n Shift-click stack: player-to-storage\n stack transfer when crafting grid\n empty, otherwise player-to-grid\n stack transfer. Automatically\n distributes the clicked stack.\n Shift-Ctrl-click stack: Move all\n same stacks. Mouse wheel over\n crafting slot: Increase/decrease\n crafting grid items.", "block.engineersdecor.metal_crafting_table.tooltips.clear": "Clear grid to player inventory", @@ -167,7 +167,7 @@ "block.engineersdecor.old_industrial_wood_slabslice": "Old Industrial Wood Slab Slice", "block.engineersdecor.old_industrial_wood_stairs": "Old Industrial Wood Stairs", "block.engineersdecor.panzerglass_block": "Panzer Glass Block", - "block.engineersdecor.panzerglass_block.help": "Reinforced glass block.\n Expensive, explosion-proof.\n Dark gray tint, faint structural\n lines visible, multi texture for\n seemless look.", + "block.engineersdecor.panzerglass_block.help": "Reinforced glass block.\n Expensive, explosion-proof.\n Dark gray tint, faint structural\n lines visible, multi texture for\n seamless look.", "block.engineersdecor.panzerglass_slab": "Panzer Glass Slab", "block.engineersdecor.panzerglass_slab.help": "Reinforced glass slab.\n Expensive, explosion-proof.\n Dark gray tint, faint structural\n lines visible.", "block.engineersdecor.rebar_concrete": "Rebar Concrete Block", @@ -223,7 +223,7 @@ "block.engineersdecor.small_lab_furnace": "Small Laboratory Furnace", "block.engineersdecor.small_lab_furnace.help": "Small metal cased lab kiln. Solid\n fuel consuming, updraught. Slightly\n hotter and better isolated than a\n cobblestone furnace, therefore\n more efficient. Two auxiliary\n slots e.g. for storage. Two stack\n internal hopper fifos for input,\n output, and fuel. Place an\n external heater into a aux slot\n and connect power for electrical\n smelting speed boost.", "block.engineersdecor.small_milking_machine": "Small Milking Machine", - "block.engineersdecor.small_milking_machine.help": "Occasionally milks cows. Has an\n internal fluid tank. Does not\n feed the animals. Use buckets to\n retrieve the milk. Pulls/stores\n milk container items from/to\n inventories at the back or bottom\n (preferrs extracting from the\n back and inserting below, but can\n also put filled vessels back into\n the same inventory). Supports fluid\n output to tanks or pipes below\n (only if milk exists as fluid).\n Care that it's not too crowdy in\n the cow pen, only happy animals\n stroll by voluntarily.", + "block.engineersdecor.small_milking_machine.help": "Occasionally milks cows. Has an\n internal fluid tank. Does not\n feed the animals. Use buckets to\n retrieve the milk. Pulls/stores\n milk container items from/to\n inventories at the back or bottom\n (prefers extracting from the\n back and inserting below, but can\n also put filled vessels back into\n the same inventory). Supports fluid\n output to tanks or pipes below\n (only if milk exists as fluid).\n Care that it's not too crowdy in\n the cow pen, only happy animals\n stroll by voluntarily.", "block.engineersdecor.small_milking_machine.status": "Milk: %1$smB %2$s", "block.engineersdecor.small_milking_machine.status.rf": "| %1$sRF", "block.engineersdecor.small_mineral_smelter": "Small Mineral Melting Furnace", @@ -232,14 +232,14 @@ "block.engineersdecor.small_solar_panel.help": "Produces a small amount of power\n when exposed to sunlight. Useful\n for charging LF capacitors in remote\n systems with low consumption. The\n internal charge pump circuit\n accumulates and frequently\n transfers RF. Production depends\n on day time and the weather.\nClick to see State Of Charge,\n production, and progress.", "block.engineersdecor.small_solar_panel.status": "SOC: %1$s%% of %2$sRF§r | producing %3$sRF/t | feeding %4$sRF/t", "block.engineersdecor.small_tree_cutter": "Small Tree Cutter", - "block.engineersdecor.small_tree_cutter.help": "Chops grown trees in front of it.\n Does not collect the lumbers.\n Deactivate with a redstone signal.\n ${!tree_cuttter_requires_power?engineersdecor.tooltip.massive_speed_boost_with_rf_power} ${tree_cuttter_requires_power?engineersdecor.tooltip.requires_rf_power}", + "block.engineersdecor.small_tree_cutter.help": "Chops grown trees in front of it.\n Does not collect the lumbers.\n Deactivate with a redstone signal.\n ${!tree_cutter_requires_power?engineersdecor.tooltip.massive_speed_boost_with_rf_power} ${tree_cutter_requires_power?engineersdecor.tooltip.requires_rf_power}", "block.engineersdecor.small_tree_cutter.status": "SOC: %1$s%% of %2$sRF§r | progress: %3$s%% (%4$ss)", "block.engineersdecor.small_waste_incinerator": "Small Waste Incinerator", "block.engineersdecor.small_waste_incinerator.help": "Trash with internal fifo slots.\n Items can be inserted on all sides,\n and are kept until there is no\n space left in the fifo. After that\n the oldest stack will be incinerated.\n Apply electrical RF/FE power to\n increase the processing speed.\n Keeps its inventory when being\n relocated.", "block.engineersdecor.steel_catwalk": "Steel Catwalk", - "block.engineersdecor.steel_catwalk.help": "Simple catwalk for better access to\nbig machines. Can also be placed in\nlook direction from the top. Click\nwith a Railing to add the guardrail\nto a side (close click: exact\nplacemend, far click: auto best\nmatch). Click again to remove a\nguardrail.", + "block.engineersdecor.steel_catwalk.help": "Simple catwalk for better access to\nbig machines. Can also be placed in\nlook direction from the top. Click\nwith a Railing to add the guardrail\nto a side (close click: exact\nplacement, far click: auto best\nmatch). Click again to remove a\nguardrail.", "block.engineersdecor.steel_catwalk_stairs": "Steel Catwalk Stairs", - "block.engineersdecor.steel_catwalk_stairs.help": "Click with a Steel Railing to add\nor remove guardrails. Cannot be\nplaced bottom-down, no corners\n(no'normal' Stairs).", + "block.engineersdecor.steel_catwalk_stairs.help": "Click with a Steel Railing to add\nor remove guardrails. Cannot be\nplaced bottom-down, no corners\n(no 'normal' Stairs).", "block.engineersdecor.steel_catwalk_ta": "Raised Steel Catwalk", "block.engineersdecor.steel_catwalk_ta.help": "Top aligned Catwalk, connects to\nSteel poles below.", "block.engineersdecor.steel_double_t_support": "Steel Double T Support", diff --git a/src/main/resources/assets/engineersdecor/lang/ru_ru.json b/src/main/resources/assets/engineersdecor/lang/ru_ru.json index a04d235..b272f29 100644 --- a/src/main/resources/assets/engineersdecor/lang/ru_ru.json +++ b/src/main/resources/assets/engineersdecor/lang/ru_ru.json @@ -145,7 +145,7 @@ "block.engineersdecor.iron_inset_light.help": "Маленький источник света, интегрируемый в стены, пол или потолок.\n Полезно для освещения мест, где проблематичны электрические осветительные установки.", "block.engineersdecor.labeled_crate": "Ящик с рамкой", "block.engineersdecor.labeled_crate.help": "Ящик для хранения со слотами 9x6 и встроенной рамкой для предмета спереди.\nПоместите предмет в слот рамки в правом нижнем углу GUI, чтобы обозначить ящик.", - "block.engineersdecor.labeled_crate.tip": "§6Метка:§r %1$s\n%2$s слотов использовано / %3$s свободно\n%4$s общее количество хранимых предметов", + "block.engineersdecor.labeled_crate.tip": "§6Метка:§r %1$s\n%2$s слотов использовано / %3$s свободно\n%4$s общее количество хранимых предметов\n---\n%5$s", "block.engineersdecor.metal_crafting_table": "Верстак из обработанного дерева", "block.engineersdecor.metal_crafting_table.help": "Прочный и устойчивый к погодным условиям. Восемь слотов для хранения. Хранит инвентарь. Нажимайте кнопки со стрелками вверх/вниз для выбора из истории, выходной слот для размещения предметов, X-кнопка очистить сетку крафта и историю. Shift-клик по стеку: передача стека от игрока в хранилище при создании если сетка пуста, в противном случае перенос от игрока в сетку. Автоматически распределяет кликаемый стек. Shift-Ctrl-клик по стаку: перемещает одинаковые стаки. Колёсико мыши: добавляет/отнимает предметы в сетке.", "block.engineersdecor.metal_crafting_table.tooltips.clear": "Очистить сетку в инвентарь игрока", @@ -232,7 +232,7 @@ "block.engineersdecor.small_solar_panel.help": "Вырабатывает небольшое количество энергии при воздействии солнечного света.\n Полезно для зарядки низковольтных конденсаторов в удаленных системах с низким потреблением.\nВнутренний контур насоса накапливает и часто передает RF.\nПроизводство зависит от времени суток и погоды.", "block.engineersdecor.small_solar_panel.status": "SOC: %1$s%% из %2$sRF§r | производит %3$sRF/тик | отдаёт %4$sRF/тик", "block.engineersdecor.small_tree_cutter": "Малый лесоруб", - "block.engineersdecor.small_tree_cutter.help": "Вырубает деревья перед ним.\n Не собирает срубленное. Выключается с помощью сигнала красного камня. ${!tree_cuttter_requires_power?engineersdecor.tooltip.massive_speed_boost_with_rf_power} ${tree_cuttter_requires_power?engineersdecor.tooltip.requires_rf_power}", + "block.engineersdecor.small_tree_cutter.help": "Вырубает деревья перед ним.\n Не собирает срубленное. Выключается с помощью сигнала красного камня. ${!tree_cutter_requires_power?engineersdecor.tooltip.massive_speed_boost_with_rf_power} ${tree_cutter_requires_power?engineersdecor.tooltip.requires_rf_power}", "block.engineersdecor.small_tree_cutter.status": "SOC: %1$s%% из %2$sRF§r | прогресс: %3$s%% (%4$sсек)", "block.engineersdecor.small_waste_incinerator": "Компактный сжигатель отходов", "block.engineersdecor.small_waste_incinerator.help": "Отходы с слотами для очереди. Предметы могут помещаться с любой стороны,\nи храниться до тех пор, пока в очереди не останется свободного места.\nПосле этого самый старый стек будет сожжен. Подключите электричество (RF/FE)\nдля увеличения скорости обработки.\nСохраняет инвентарь при перемещении.", diff --git a/src/main/resources/assets/engineersdecor/lang/zh_cn.json b/src/main/resources/assets/engineersdecor/lang/zh_cn.json index a151f2c..7eed4ca 100644 --- a/src/main/resources/assets/engineersdecor/lang/zh_cn.json +++ b/src/main/resources/assets/engineersdecor/lang/zh_cn.json @@ -145,7 +145,7 @@ "block.engineersdecor.iron_inset_light.help": "§6小型荧石光源,能嵌入地板、天花板或墙里。§r\n 用于照亮电力光源难以安装的地方。 亮度与火把一样。", "block.engineersdecor.labeled_crate": "贴标签的板条箱", "block.engineersdecor.labeled_crate.help": "§6具备 9x6 大小格子的木箱,前面自带一个物品展示框。§r\n将物品放置在 GUI 右下角的框架槽内,可以定义所显示的标签。", - "block.engineersdecor.labeled_crate.tip": "§6标签:§r %1$s\n已使用 %2$s / 剩余 %3$s \n共存储 %4$s 件物品", + "block.engineersdecor.labeled_crate.tip": "§6标签:§r %1$s\n已使用 %2$s / 剩余 %3$s \n共存储 %4$s 件物品\n---\n%5$s", "block.engineersdecor.metal_crafting_table": "防腐木合成台", "block.engineersdecor.metal_crafting_table.help": "§6坚固,防风防雨。§r内含八个存储格,破坏后保留内容物,没有原版合成书。\n 单击上/下箭头按钮可选择合成历史,单击输出格自动放置物品,单击X按钮 清除合成栏和历史。Shift单击一叠物品:合成格空时转移到存储格, 非空时到合成栏。会自动分配转移的物品。", "block.engineersdecor.metal_crafting_table.tooltips.clear": "Clear grid to player inventory", diff --git a/src/main/resources/data/engineersdecor/recipes/independent/clinker_brick_recipe2.json b/src/main/resources/data/engineersdecor/recipes/independent/clinker_brick_recipe2.json new file mode 100644 index 0000000..df38057 --- /dev/null +++ b/src/main/resources/data/engineersdecor/recipes/independent/clinker_brick_recipe2.json @@ -0,0 +1,30 @@ +{ + "type": "forge:conditional", + "recipes": [ + { + "conditions": [ + { + "type": "engineersdecor:optional", + "result": "engineersdecor:clinker_brick_block" + } + ], + "recipe": { + "type": "minecraft:crafting_shaped", + "pattern": [ + "BAB", + "ANA", + "BAB" + ], + "key": { + "A": { "item": "minecraft:brick" }, + "B": { "tag" : "engineersdecor:brick_ingots" }, + "N": { "item": "minecraft:bricks" } + }, + "result": { + "item": "engineersdecor:clinker_brick_block", + "count": 8 + } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/engineersdecor/recipes/independent/treated_wood_ladder_recipe.json b/src/main/resources/data/engineersdecor/recipes/independent/treated_wood_ladder_recipe.json index 82d9dd5..438aae2 100644 --- a/src/main/resources/data/engineersdecor/recipes/independent/treated_wood_ladder_recipe.json +++ b/src/main/resources/data/engineersdecor/recipes/independent/treated_wood_ladder_recipe.json @@ -1,6 +1,30 @@ { "type": "forge:conditional", "recipes": [ + { + "conditions": [ + { + "type": "engineersdecor:optional", + "result": "engineersdecor:treated_wood_ladder", + "required": ["#forge:treated_wood"] + } + ], + "recipe": { + "type": "minecraft:crafting_shaped", + "pattern": [ + "S S", + "SSS", + "S S" + ], + "key": { + "S": { "tag": "forge:treated_wood" } + }, + "result": { + "item": "engineersdecor:treated_wood_ladder", + "count": 8 + } + } + }, { "conditions": [ { @@ -21,31 +45,7 @@ }, "result": { "item": "engineersdecor:treated_wood_ladder", - "count": 6 - } - } - }, - { - "conditions": [ - { - "type": "engineersdecor:optional", - "result": "engineersdecor:treated_wood_ladder", - "required": ["minecraft:ladder"] - } - ], - "recipe": { - "type": "minecraft:crafting_shaped", - "pattern": [ - "S S", - "SSS", - "S S" - ], - "key": { - "S": { "item": "minecraft:ladder"} - }, - "result": { - "item": "engineersdecor:treated_wood_ladder", - "count": 7 + "count": 8 } } }