Crafting Table grid shift/ctrl-click interactions go first to storage, then to player inventory. Fixed Lab Furnace speed boost using IE External Heater.

This commit is contained in:
stfwi 2020-10-17 09:01:24 +02:00
parent a730143176
commit ed54eea0bd
12 changed files with 481 additions and 373 deletions

View file

@ -5,4 +5,4 @@ version_minecraft=1.16.3
version_forge_minecraft=1.16.3-34.1.0 version_forge_minecraft=1.16.3-34.1.0
version_fml_mappings=20200723-1.16.1 version_fml_mappings=20200723-1.16.1
version_jei=1.16.3:7.3.2.36 version_jei=1.16.3:7.3.2.36
version_engineersdecor=1.1.3-b1 version_engineersdecor=1.1.3-b2

View file

@ -1,6 +1,7 @@
{ {
"homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/", "homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/",
"1.16.3": { "1.16.3": {
"1.1.3-b2": "[A] Crafting table shift/ctrl click item move actions tweaked to new metal slot design.\n[A] Factory Dropper and Block Placer now also support quick-move-all (shift-ctrl-click).\n[F] Fixed Small Lab Furnace speed boost factor (with IE Heater in aux slot).",
"1.1.3-b1": "[A] The Factory Block Breaker can insert items into Hoppers underneath it (issue #121, winsrp).\n[F] Help tooltips manually wrapped.\n[F] Fixed Labeled Crate item name persistence (issue #127, ty inqie).\n[F] Help text typo fixed (issue #129, ty Smollet777).", "1.1.3-b1": "[A] The Factory Block Breaker can insert items into Hoppers underneath it (issue #121, winsrp).\n[F] Help tooltips manually wrapped.\n[F] Fixed Labeled Crate item name persistence (issue #127, ty inqie).\n[F] Help text typo fixed (issue #129, ty Smollet777).",
"1.1.2": "[U] Updated to Forge 1.16.3-34.1.0.\n[A] Added Factory Hopper insertion/extraction for entities like Minecarts (issue #125, ty boneskull).", "1.1.2": "[U] Updated to Forge 1.16.3-34.1.0.\n[A] Added Factory Hopper insertion/extraction for entities like Minecarts (issue #125, ty boneskull).",
"1.1.2-b8": "[F] Fixed Double-T support thick steel pole connection (thx @CastCrafter).\n[A] Concrete and Clinker walls connect to windows and glass panes.", "1.1.2-b8": "[F] Fixed Double-T support thick steel pole connection (thx @CastCrafter).\n[A] Concrete and Clinker walls connect to windows and glass panes.",
@ -14,6 +15,6 @@
}, },
"promos": { "promos": {
"1.16.3-recommended": "1.1.2", "1.16.3-recommended": "1.1.2",
"1.16.3-latest": "1.1.3-b1" "1.16.3-latest": "1.1.3-b2"
} }
} }

View file

@ -11,6 +11,10 @@ Mod sources for Minecraft version 1.16.3.
## Version history ## Version history
- v1.1.3-b2 [A] Crafting table shift/ctrl click item move actions tweaked to new metal slot design.
[A] Factory Dropper and Block Placer now also support quick-move-all (shift-ctrl-click).
[F] Fixed Small Lab Furnace speed boost factor (with IE Heater in aux slot).
- v1.1.3-b1 [A] The Factory Block Breaker can insert items into Hoppers underneath it (issue #121, winsrp). - v1.1.3-b1 [A] The Factory Block Breaker can insert items into Hoppers underneath it (issue #121, winsrp).
[F] Help tooltips manually wrapped. [F] Help tooltips manually wrapped.
[F] Fixed Labeled Crate item name persistence (issue #127, ty inqie). [F] Fixed Labeled Crate item name persistence (issue #127, ty inqie).

View file

@ -50,7 +50,7 @@ import wile.engineersdecor.ModContent;
import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.libmc.detail.Auxiliaries; import wile.engineersdecor.libmc.detail.Auxiliaries;
import wile.engineersdecor.libmc.detail.Inventories; import wile.engineersdecor.libmc.detail.Inventories;
import wile.engineersdecor.libmc.detail.Inventories.SlotRange; import wile.engineersdecor.libmc.detail.Inventories.InventoryRange;
import wile.engineersdecor.libmc.detail.Networking; import wile.engineersdecor.libmc.detail.Networking;
import wile.engineersdecor.libmc.detail.TooltipDisplay; import wile.engineersdecor.libmc.detail.TooltipDisplay;
import wile.engineersdecor.libmc.detail.TooltipDisplay.TipRange; import wile.engineersdecor.libmc.detail.TooltipDisplay.TipRange;
@ -158,7 +158,10 @@ public class EdCraftingTable
public static class CraftingTableTileEntity extends TileEntity implements IInventory, INameable, INamedContainerProvider public static class CraftingTableTileEntity extends TileEntity implements IInventory, INameable, INamedContainerProvider
{ {
public static final int NUM_OF_SLOTS = 9+18; public static final int NUM_OF_STORAGE_SLOTS = 18;
public static final int NUM_OF_STORAGE_ROWS = 2;
public static final int NUM_OF_SLOTS = 9+NUM_OF_STORAGE_SLOTS;
protected NonNullList<ItemStack> stacks = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY); protected NonNullList<ItemStack> stacks = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
protected CompoundNBT history = new CompoundNBT(); protected CompoundNBT history = new CompoundNBT();
@ -319,13 +322,15 @@ public class EdCraftingTable
protected static final String ACTION_PLACE_CURRENT_HISTORY_SEL = "place-refab"; protected static final String ACTION_PLACE_CURRENT_HISTORY_SEL = "place-refab";
protected static final String ACTION_PLACE_SHIFTCLICKED_STACK = "place-stack"; protected static final String ACTION_PLACE_SHIFTCLICKED_STACK = "place-stack";
protected static final String ACTION_MOVE_ALL_STACKS = "move-stacks"; protected static final String ACTION_MOVE_ALL_STACKS = "move-stacks";
protected static final String ACTION_MOVE_STACK = "move-stack";
protected static final String ACTION_INCREASE_CRAFTING_STACKS = "inc-crafting-stacks"; protected static final String ACTION_INCREASE_CRAFTING_STACKS = "inc-crafting-stacks";
protected static final String ACTION_DECREASE_CRAFTING_STACKS = "dec-crafting-stacks"; protected static final String ACTION_DECREASE_CRAFTING_STACKS = "dec-crafting-stacks";
public static final int CRAFTING_SLOTS_BEGIN = 0; public static final int CRAFTING_SLOTS_BEGIN = 0;
public static final int NUM_OF_CRAFTING_SLOTS = 9; public static final int NUM_OF_CRAFTING_SLOTS = 9;
public static final int STORAGE_SLOTS_BEGIN = NUM_OF_CRAFTING_SLOTS; public static final int STORAGE_SLOTS_BEGIN = NUM_OF_CRAFTING_SLOTS;
public static final int NUM_OF_STORAGE_SLOTS = CraftingTableTileEntity.NUM_OF_SLOTS - NUM_OF_CRAFTING_SLOTS; 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;
public final ImmutableList<Tuple<Integer,Integer>> CRAFTING_SLOT_COORDINATES; public final ImmutableList<Tuple<Integer,Integer>> CRAFTING_SLOT_COORDINATES;
private final PlayerEntity player_; private final PlayerEntity player_;
@ -336,6 +341,12 @@ public class EdCraftingTable
private final CraftResultInventory result_; private final CraftResultInventory result_;
private boolean has_recipe_collision_; private boolean has_recipe_collision_;
private boolean crafting_matrix_changed_now_; private boolean crafting_matrix_changed_now_;
private final InventoryRange crafting_grid_range_;
private final InventoryRange crafting_result_range_;
private final InventoryRange block_storage_range_;
private final InventoryRange player_storage_range_;
private final InventoryRange player_hotbar_range_;
private final InventoryRange player_inventory_range_;
public CraftingTableContainer(int cid, PlayerInventory pinv) public CraftingTableContainer(int cid, PlayerInventory pinv)
{ this(cid, pinv, new Inventory(CraftingTableTileEntity.NUM_OF_SLOTS), IWorldPosCallable.DUMMY); } { this(cid, pinv, new Inventory(CraftingTableTileEntity.NUM_OF_SLOTS), IWorldPosCallable.DUMMY); }
@ -352,6 +363,12 @@ public class EdCraftingTable
result_ = new CraftResultInventory(); result_ = new CraftResultInventory();
matrix_ = new CraftingTableGrid(this, block_inventory); matrix_ = new CraftingTableGrid(this, block_inventory);
matrix_.openInventory(player_); 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);
player_storage_range_ = InventoryRange.fromPlayerStorage(player_);
player_hotbar_range_ = InventoryRange.fromPlayerHotbar(player_);
player_inventory_range_= InventoryRange.fromPlayerInventory(player_);
// container slotId 0 === crafting output // container slotId 0 === crafting output
addSlot(new CraftingOutputSlot(this, pinv.player, matrix_, result_, 0, 118, 27)); addSlot(new CraftingOutputSlot(this, pinv.player, matrix_, result_, 0, 118, 27));
ArrayList<Tuple<Integer,Integer>> slotpositions = new ArrayList<Tuple<Integer,Integer>>(); ArrayList<Tuple<Integer,Integer>> slotpositions = new ArrayList<Tuple<Integer,Integer>>();
@ -378,7 +395,7 @@ public class EdCraftingTable
// container slotId 46..53 === TE slots 9..17 (storage) // container slotId 46..53 === TE slots 9..17 (storage)
for(int y=0; y<2; ++y) { for(int y=0; y<2; ++y) {
for(int x=0; x<9; ++x) { for(int x=0; x<9; ++x) {
addSlot(new Slot(matrix_, 9+x+y*9, 8+x*18, 65+y*18)); addSlot(new Slot(inventory_, 9+x+y*9, 8+x*18, 65+y*18));
} }
} }
if((!player_.world.isRemote) && (inventory_ instanceof CraftingTableTileEntity)) { if((!player_.world.isRemote) && (inventory_ instanceof CraftingTableTileEntity)) {
@ -522,39 +539,36 @@ public class EdCraftingTable
history_.next(); history_.next();
syncHistory(); syncHistory();
// implicitly clear the grid, so that the player can see the refab, and that no recipe is active. // implicitly clear the grid, so that the player can see the refab, and that no recipe is active.
if(clear_grid_to_player(player)) { changed = true; player_inventory_changed = true; }
if(clear_grid_to_storage(player)) changed = true; if(clear_grid_to_storage(player)) changed = true;
if(clear_grid_to_player(player)) { changed = true; player_inventory_changed = true; }
} break; } break;
case BUTTON_PREV: { case BUTTON_PREV: {
history_.prev(); history_.prev();
syncHistory(); syncHistory();
if(clear_grid_to_player(player)) { changed = true; player_inventory_changed = true; }
if(clear_grid_to_storage(player)) changed = true; if(clear_grid_to_storage(player)) changed = true;
if(clear_grid_to_player(player)) { changed = true; player_inventory_changed = true; }
} break; } break;
case BUTTON_CLEAR_GRID: { case BUTTON_CLEAR_GRID: {
history_.reset_selection(); history_.reset_selection();
syncHistory(); syncHistory();
if(clear_grid_to_player(player)) { changed = true; player_inventory_changed = true; }
if(clear_grid_to_storage(player)) changed = true; if(clear_grid_to_storage(player)) changed = true;
if(clear_grid_to_player(player)) { changed = true; player_inventory_changed = true; }
} break; } break;
case ACTION_PLACE_CURRENT_HISTORY_SEL: { case ACTION_PLACE_CURRENT_HISTORY_SEL: {
if(place_stacks(new SlotRange[]{ if(place_stacks(
new SlotRange(player.inventory, 0, 9), new InventoryRange[]{block_storage_range_, player_storage_range_, player_hotbar_range_},
new SlotRange(player.inventory, 9, 36), refab_crafting_stacks()) != PlacementResult.UNCHANGED) {
new SlotRange(inventory_, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN+NUM_OF_STORAGE_SLOTS)
}, refab_crafting_stacks()) != PlacementResult.UNCHANGED) {
changed = true; changed = true;
} }
} break; } break;
case ACTION_PLACE_SHIFTCLICKED_STACK: { case ACTION_PLACE_SHIFTCLICKED_STACK: {
final int container_slot_id = nbt.getInt("containerslot"); final int container_slot_id = nbt.getInt("containerslot");
if((container_slot_id < 10) || (container_slot_id > 53)) { if((container_slot_id < 10) || (container_slot_id > (46+NUM_OF_STORAGE_SLOTS))) {
break; // out of range break; // out of range
} }
if(container_slot_id >= 46) { if(container_slot_id >= 46) {
// from storage // from storage
final int storage_slot = container_slot_id - 46 + STORAGE_SLOTS_BEGIN; PlacementResult stat = distribute_stack(block_storage_range_, container_slot_id-46);
PlacementResult stat = distribute_stack(inventory_, storage_slot);
if(stat != PlacementResult.UNCHANGED) changed = true; if(stat != PlacementResult.UNCHANGED) changed = true;
} else { } else {
// from player // from player
@ -573,6 +587,20 @@ public class EdCraftingTable
} }
} }
} break; } break;
case ACTION_MOVE_STACK: {
final int container_slot_id = nbt.getInt("containerslot");
if((container_slot_id < 1) || (container_slot_id >= (46+NUM_OF_STORAGE_SLOTS))) {
break; // out of range
} else if(container_slot_id < 10) {
int slot = container_slot_id;
ItemStack remaining = Inventories.insert(
new InventoryRange[] {block_storage_range_, player_storage_range_, player_hotbar_range_},
inventory_.getStackInSlot(slot-1)
);
changed = player_inventory_changed = (remaining.getCount()!=inventory_.getStackInSlot(slot-1).getCount());
inventory_.setInventorySlotContents(slot-1, remaining);
}
} break;
case ACTION_MOVE_ALL_STACKS: { case ACTION_MOVE_ALL_STACKS: {
final int container_slot_id = nbt.getInt("containerslot"); final int container_slot_id = nbt.getInt("containerslot");
if((container_slot_id < 1) || (container_slot_id >= (46+NUM_OF_STORAGE_SLOTS))) { if((container_slot_id < 1) || (container_slot_id >= (46+NUM_OF_STORAGE_SLOTS))) {
@ -580,23 +608,23 @@ public class EdCraftingTable
} else if(container_slot_id < 10) { } else if(container_slot_id < 10) {
// from crafting grid to player inventory, we clear the grid here as this is most likely // 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. // what is wanted in the end. Saves clicking the other grid stacks.
if(clear_grid_to_player(player)) { changed = true; player_inventory_changed = true; }
if(clear_grid_to_storage(player)) changed = true; if(clear_grid_to_storage(player)) changed = true;
if(clear_grid_to_player(player)) { changed = true; player_inventory_changed = true; }
break; break;
} }
IInventory from_inventory; IInventory from_inventory;
SlotRange[] to_ranges; InventoryRange[] to_ranges;
int from_slot; int from_slot;
if(container_slot_id >= 46) { if(container_slot_id >= 46) {
// from storage to player inventory // from storage to player inventory
from_inventory = inventory_; from_inventory = inventory_;
from_slot = container_slot_id - 46 + STORAGE_SLOTS_BEGIN; from_slot = container_slot_id - 46 + STORAGE_SLOTS_BEGIN;
to_ranges = new SlotRange[] {new SlotRange(player.inventory, 9, 36), new SlotRange(player.inventory, 0, 9)}; to_ranges = new InventoryRange[] {player_storage_range_, player_hotbar_range_};
} else { } else {
// from player to storage (otherwise ACTION_PLACE_SHIFTCLICKED_STACK would have been used) // from player to storage (otherwise ACTION_PLACE_SHIFTCLICKED_STACK would have been used)
from_inventory = player.inventory; from_inventory = player.inventory;
from_slot = (container_slot_id >= 37) ? (container_slot_id-37) : (container_slot_id-10+9); from_slot = (container_slot_id >= 37) ? (container_slot_id-37) : (container_slot_id-10+9);
to_ranges = new SlotRange[] {new SlotRange(inventory_, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN+NUM_OF_STORAGE_SLOTS)}; to_ranges = new InventoryRange[]{block_storage_range_};
} }
final ItemStack reference_stack = from_inventory.getStackInSlot(from_slot).copy(); final ItemStack reference_stack = from_inventory.getStackInSlot(from_slot).copy();
if(!reference_stack.isEmpty()) { if(!reference_stack.isEmpty()) {
@ -604,16 +632,8 @@ public class EdCraftingTable
for(int i=0; (i < from_inventory.getSizeInventory()) && (!abort); ++i) { for(int i=0; (i < from_inventory.getSizeInventory()) && (!abort); ++i) {
final ItemStack stack = from_inventory.getStackInSlot(i); final ItemStack stack = from_inventory.getStackInSlot(i);
if(Inventories.areItemStacksDifferent(reference_stack, stack)) continue; if(Inventories.areItemStacksDifferent(reference_stack, stack)) continue;
ItemStack remaining = from_inventory.getStackInSlot(i); ItemStack remaining = Inventories.insert(to_ranges, from_inventory.getStackInSlot(i));
for(SlotRange range:to_ranges) { changed = player_inventory_changed = (remaining.getCount()!=from_inventory.getStackInSlot(i).getCount());
remaining = range.insert(remaining, false, 0, false, true);
if(!remaining.isEmpty()) {
abort = true; // no space left
break;
} else {
changed = player_inventory_changed = true;
}
}
from_inventory.setInventorySlotContents(i, remaining); from_inventory.setInventorySlotContents(i, remaining);
} }
} }
@ -622,18 +642,14 @@ public class EdCraftingTable
select_next_collision_recipe(inventory_); select_next_collision_recipe(inventory_);
} break; } break;
case ACTION_DECREASE_CRAFTING_STACKS: { case ACTION_DECREASE_CRAFTING_STACKS: {
changed = player_inventory_changed = decrease_grid_stacks(new SlotRange[]{ changed = player_inventory_changed = decrease_grid_stacks(
new SlotRange(player.inventory, 9, 36), new InventoryRange[]{block_storage_range_, player_storage_range_, player_hotbar_range_},
new SlotRange(player.inventory, 0, 9), MathHelper.clamp(nbt.getInt("limit"), 1, 8));
new SlotRange(inventory_, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN+NUM_OF_STORAGE_SLOTS)
}, MathHelper.clamp(nbt.getInt("limit"), 1, 8));
} break; } break;
case ACTION_INCREASE_CRAFTING_STACKS: { case ACTION_INCREASE_CRAFTING_STACKS: {
changed = player_inventory_changed = increase_grid_stacks(new SlotRange[]{ changed = player_inventory_changed = increase_grid_stacks(
new SlotRange(player.inventory, 9, 36), new InventoryRange[]{block_storage_range_, player_storage_range_, player_hotbar_range_},
new SlotRange(player.inventory, 0, 9), MathHelper.clamp(nbt.getInt("limit"), 1, 8));
new SlotRange(inventory_, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN+NUM_OF_STORAGE_SLOTS)
}, MathHelper.clamp(nbt.getInt("limit"), 1, 8));
} break; } break;
} }
} }
@ -717,26 +733,22 @@ public class EdCraftingTable
.findFirst().orElse(null); .findFirst().orElse(null);
} }
private ItemStack search_inventory(ItemStack match_stack, ItemStack not_found_value) { private Optional<ItemStack> search_inventory(ItemStack match_stack) {
SlotRange search_ranges[] = new SlotRange[]{ InventoryRange search_ranges[] = new InventoryRange[]{block_storage_range_, player_storage_range_, player_hotbar_range_};
new SlotRange(player_.inventory, 0, 36), for(InventoryRange range: search_ranges) {
new SlotRange(inventory_, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN+NUM_OF_STORAGE_SLOTS) for(int i=0; i<range.getSizeInventory(); ++i) {
}; if(Inventories.areItemStacksIdentical(range.getStackInSlot(i), match_stack)) return Optional.of(match_stack);
for(SlotRange range: search_ranges) {
for(int i=0; i<range.inventory.getSizeInventory(); ++i) {
ItemStack stack = range.inventory.getStackInSlot(i);
if(Inventories.areItemStacksIdentical(stack, match_stack)) return match_stack;
} }
} }
return not_found_value; return Optional.empty();
} }
private ItemStack search_inventory(ItemStack[] match_stacks, ItemStack not_found_value) { private Optional<ItemStack> search_inventory(ItemStack[] match_stacks) {
for(ItemStack match_stack: match_stacks) { for(ItemStack match_stack: match_stacks) {
ItemStack stack = search_inventory(match_stack, ItemStack.EMPTY); Optional<ItemStack> stack = search_inventory(match_stack);
if(!stack.isEmpty()) return stack; if(stack.isPresent()) return stack;
} }
return not_found_value; return Optional.empty();
} }
private ArrayList<ItemStack> placement_stacks(ICraftingRecipe recipe) private ArrayList<ItemStack> placement_stacks(ICraftingRecipe recipe)
@ -756,7 +768,7 @@ public class EdCraftingTable
if((w >= endw) || (ingredient_index >= recipe.getIngredients().size())) { grid.add(ItemStack.EMPTY); continue; } if((w >= endw) || (ingredient_index >= recipe.getIngredients().size())) { grid.add(ItemStack.EMPTY); continue; }
ItemStack[] match_stacks = recipe.getIngredients().get(ingredient_index++).getMatchingStacks(); ItemStack[] match_stacks = recipe.getIngredients().get(ingredient_index++).getMatchingStacks();
if(match_stacks.length == 0) { grid.add(ItemStack.EMPTY); continue; } if(match_stacks.length == 0) { grid.add(ItemStack.EMPTY); continue; }
ItemStack preferred = search_inventory(match_stacks, match_stacks[0]); ItemStack preferred = search_inventory(match_stacks).orElse(match_stacks[0]);
if(preferred.isEmpty()) { grid.add(ItemStack.EMPTY); continue; } if(preferred.isEmpty()) { grid.add(ItemStack.EMPTY); continue; }
grid.add(preferred); grid.add(preferred);
} }
@ -765,7 +777,7 @@ public class EdCraftingTable
for(int ingredient_index=0; ingredient_index<recipe.getIngredients().size(); ++ingredient_index) { for(int ingredient_index=0; ingredient_index<recipe.getIngredients().size(); ++ingredient_index) {
ItemStack[] match_stacks = recipe.getIngredients().get(ingredient_index).getMatchingStacks(); ItemStack[] match_stacks = recipe.getIngredients().get(ingredient_index).getMatchingStacks();
if(match_stacks.length == 0) { grid.add(ItemStack.EMPTY); continue; } if(match_stacks.length == 0) { grid.add(ItemStack.EMPTY); continue; }
ItemStack preferred = search_inventory(match_stacks, match_stacks[0]); ItemStack preferred = search_inventory(match_stacks).orElse(match_stacks[0]);
if(preferred.isEmpty()) { grid.add(ItemStack.EMPTY); continue; } if(preferred.isEmpty()) { grid.add(ItemStack.EMPTY); continue; }
grid.add(preferred); grid.add(preferred);
} }
@ -781,11 +793,11 @@ public class EdCraftingTable
for(int stack_index=0; stack_index < grid_stacks.size(); ++stack_index) { for(int stack_index=0; stack_index < grid_stacks.size(); ++stack_index) {
ItemStack to_replace = grid_stacks.get(stack_index); ItemStack to_replace = grid_stacks.get(stack_index);
ItemStack replacement = to_replace; ItemStack replacement = to_replace;
if(to_replace.isEmpty() || (!search_inventory(to_replace, ItemStack.EMPTY).isEmpty())) continue; // no replacement needed if(to_replace.isEmpty() || (search_inventory(to_replace).isPresent())) continue; // no replacement needed
for(int ingredient_index=0; ingredient_index<recipe.getIngredients().size(); ++ingredient_index) { for(int ingredient_index=0; ingredient_index<recipe.getIngredients().size(); ++ingredient_index) {
ItemStack[] match_stacks = recipe.getIngredients().get(ingredient_index).getMatchingStacks(); ItemStack[] match_stacks = recipe.getIngredients().get(ingredient_index).getMatchingStacks();
if(Arrays.stream(match_stacks).anyMatch(s->Inventories.areItemStacksIdentical(s, to_replace))) { if(Arrays.stream(match_stacks).anyMatch(s->Inventories.areItemStacksIdentical(s, to_replace))) {
replacement = search_inventory(match_stacks, to_replace); replacement = search_inventory(match_stacks).orElse(to_replace);
changed = true; changed = true;
break; break;
} }
@ -889,7 +901,7 @@ public class EdCraftingTable
{ {
final ArrayList<ItemStack> stacks = new ArrayList<ItemStack>(); final ArrayList<ItemStack> stacks = new ArrayList<ItemStack>();
for(int i=0; i<9; ++i) { for(int i=0; i<9; ++i) {
final ItemStack palced = inventory_.getStackInSlot(i+CRAFTING_SLOTS_BEGIN).copy(); final ItemStack palced = crafting_grid_range_.getStackInSlot(i).copy();
if(!palced.isEmpty()) palced.setCount(count); if(!palced.isEmpty()) palced.setCount(count);
stacks.add(palced); stacks.add(palced);
} }
@ -897,45 +909,22 @@ public class EdCraftingTable
} }
private boolean clear_grid_to_storage(PlayerEntity player) private boolean clear_grid_to_storage(PlayerEntity player)
{ { return crafting_grid_range_.move(block_storage_range_); }
boolean changed = false;
for(int grid_i = CRAFTING_SLOTS_BEGIN; grid_i < (CRAFTING_SLOTS_BEGIN+NUM_OF_CRAFTING_SLOTS); ++grid_i) {
ItemStack stack = inventory_.getStackInSlot(grid_i);
if(stack.isEmpty()) continue;
ItemStack remaining = (new SlotRange(inventory_, STORAGE_SLOTS_BEGIN, STORAGE_SLOTS_BEGIN+NUM_OF_STORAGE_SLOTS)).insert(stack, false, 0);
inventory_.setInventorySlotContents(grid_i, remaining);
changed = true;
}
return changed;
}
private boolean clear_grid_to_player(PlayerEntity player) private boolean clear_grid_to_player(PlayerEntity player)
{ { return crafting_grid_range_.move(player_inventory_range_); }
boolean changed = false;
for(int grid_i = CRAFTING_SLOTS_BEGIN; grid_i < (CRAFTING_SLOTS_BEGIN+NUM_OF_CRAFTING_SLOTS); ++grid_i) {
ItemStack remaining = inventory_.getStackInSlot(grid_i);
if(remaining.isEmpty()) continue;
remaining = (new SlotRange(player.inventory,9, 36)).insert(remaining,true, 0); // prefer filling up inventory stacks
remaining = (new SlotRange(player.inventory,0, 9)).insert(remaining, true, 0); // then fill up the hotbar stacks
remaining = (new SlotRange(player.inventory,9, 36)).insert(remaining, false, 0); // then allow empty stacks in inventory
remaining = (new SlotRange(player.inventory,0, 9)).insert(remaining, false, 0); // then new stacks in the hotbar
inventory_.setInventorySlotContents(grid_i, remaining);
changed = true;
}
return changed;
}
private PlacementResult place_stacks(final SlotRange[] ranges, final List<ItemStack> to_fill) private PlacementResult place_stacks(final InventoryRange[] ranges, final List<ItemStack> to_fill)
{ {
if(history_.current_recipe() != null) result_.setRecipeUsed(history_.current_recipe()); if(history_.current_recipe() != null) result_.setRecipeUsed(history_.current_recipe());
boolean slots_changed = false; boolean slots_changed = false;
if(!to_fill.isEmpty()) { if(!to_fill.isEmpty()) {
for(SlotRange slot_range: ranges) { for(InventoryRange slot_range: ranges) {
for(int it_guard=63; it_guard>=0; --it_guard) { for(int it_guard=63; it_guard>=0; --it_guard) {
boolean slots_updated = false; boolean slots_updated = false;
for(int i = 0; i < 9; ++i) { for(int i = 0; i < 9; ++i) {
if(to_fill.get(i).isEmpty()) continue; if(to_fill.get(i).isEmpty()) continue;
ItemStack grid_stack = inventory_.getStackInSlot(i + CRAFTING_SLOTS_BEGIN).copy(); ItemStack grid_stack = crafting_grid_range_.getStackInSlot(i).copy();
if(grid_stack.getCount() >= grid_stack.getMaxStackSize()) continue; if(grid_stack.getCount() >= grid_stack.getMaxStackSize()) continue;
final ItemStack req_stack = to_fill.get(i).copy(); final ItemStack req_stack = to_fill.get(i).copy();
req_stack.setCount(1); req_stack.setCount(1);
@ -947,7 +936,7 @@ public class EdCraftingTable
} else { } else {
grid_stack.grow(mv_stack.getCount()); grid_stack.grow(mv_stack.getCount());
} }
inventory_.setInventorySlotContents(i + CRAFTING_SLOTS_BEGIN, grid_stack); crafting_grid_range_.setInventorySlotContents(i, grid_stack);
slots_changed = true; slots_changed = true;
slots_updated = true; slots_updated = true;
} }
@ -971,18 +960,18 @@ public class EdCraftingTable
} }
} }
private PlacementResult distribute_stack(IInventory inventory, final int slotno) private PlacementResult distribute_stack(IInventory inventory, final int slot_index)
{ {
List<ItemStack> to_refab = refab_crafting_stacks(); List<ItemStack> to_refab = refab_crafting_stacks();
if(history_.current_recipe() != null) result_.setRecipeUsed(history_.current_recipe()); if(history_.current_recipe() != null) result_.setRecipeUsed(history_.current_recipe());
ItemStack to_distribute = inventory.getStackInSlot(slotno).copy(); ItemStack to_distribute = inventory.getStackInSlot(slot_index).copy();
if(to_distribute.isEmpty()) return PlacementResult.UNCHANGED; if(to_distribute.isEmpty()) return PlacementResult.UNCHANGED;
int matching_grid_stack_sizes[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1}; int matching_grid_stack_sizes[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1};
int max_matching_stack_size = -1; int max_matching_stack_size = -1;
int min_matching_stack_size = 65; int min_matching_stack_size = 65;
int total_num_missing_stacks = 0; int total_num_missing_stacks = 0;
for(int i=0; i<9; ++i) { for(int i=0; i<9; ++i) {
final ItemStack grid_stack = inventory_.getStackInSlot(i+CRAFTING_SLOTS_BEGIN); final ItemStack grid_stack = crafting_grid_range_.getStackInSlot(i);
final ItemStack refab_stack = to_refab.isEmpty() ? ItemStack.EMPTY : to_refab.get(i).copy(); final ItemStack refab_stack = to_refab.isEmpty() ? ItemStack.EMPTY : to_refab.get(i).copy();
if((!grid_stack.isEmpty()) && Inventories.areItemStacksIdentical(grid_stack, to_distribute)) { if((!grid_stack.isEmpty()) && Inventories.areItemStacksIdentical(grid_stack, to_distribute)) {
matching_grid_stack_sizes[i] = grid_stack.getCount(); matching_grid_stack_sizes[i] = grid_stack.getCount();
@ -1004,7 +993,7 @@ public class EdCraftingTable
} }
} }
if(min_matching_stack_size < 0) return PlacementResult.UNCHANGED; if(min_matching_stack_size < 0) return PlacementResult.UNCHANGED;
final int stack_limit_size = Math.min(to_distribute.getMaxStackSize(), inventory_.getInventoryStackLimit()); final int stack_limit_size = Math.min(to_distribute.getMaxStackSize(), crafting_grid_range_.getInventoryStackLimit());
if(min_matching_stack_size >= stack_limit_size) return PlacementResult.UNCHANGED; if(min_matching_stack_size >= stack_limit_size) return PlacementResult.UNCHANGED;
int n_to_distribute = to_distribute.getCount(); int n_to_distribute = to_distribute.getCount();
for(int it_guard=63; it_guard>=0; --it_guard) { for(int it_guard=63; it_guard>=0; --it_guard) {
@ -1026,40 +1015,40 @@ public class EdCraftingTable
} }
if(n_to_distribute == to_distribute.getCount()) return PlacementResult.UNCHANGED; // was already full if(n_to_distribute == to_distribute.getCount()) return PlacementResult.UNCHANGED; // was already full
if(n_to_distribute <= 0) { if(n_to_distribute <= 0) {
inventory.setInventorySlotContents(slotno, ItemStack.EMPTY); inventory.setInventorySlotContents(slot_index, ItemStack.EMPTY);
} else { } else {
to_distribute.setCount(n_to_distribute); to_distribute.setCount(n_to_distribute);
inventory.setInventorySlotContents(slotno, to_distribute); inventory.setInventorySlotContents(slot_index, to_distribute);
} }
for(int i=0; i<9; ++i) { for(int i=0; i<9; ++i) {
if(matching_grid_stack_sizes[i] < 0) continue; if(matching_grid_stack_sizes[i] < 0) continue;
ItemStack grid_stack = inventory_.getStackInSlot(i + CRAFTING_SLOTS_BEGIN).copy(); ItemStack grid_stack = crafting_grid_range_.getStackInSlot(i).copy();
if(grid_stack.isEmpty()) grid_stack = to_distribute.copy(); if(grid_stack.isEmpty()) grid_stack = to_distribute.copy();
grid_stack.setCount(matching_grid_stack_sizes[i]); grid_stack.setCount(matching_grid_stack_sizes[i]);
inventory_.setInventorySlotContents(i + CRAFTING_SLOTS_BEGIN, grid_stack); crafting_grid_range_.setInventorySlotContents(i, grid_stack);
} }
return PlacementResult.PLACED; return PlacementResult.PLACED;
} }
private boolean decrease_grid_stacks(SlotRange[] ranges, int limit) private boolean decrease_grid_stacks(InventoryRange[] ranges, int limit)
{ {
boolean changed = false; boolean changed = false;
for(int i=0; i<9; ++i) { for(int i=0; i<9; ++i) {
ItemStack stack = inventory_.getStackInSlot(i+CRAFTING_SLOTS_BEGIN).copy(); ItemStack stack = crafting_grid_range_.getStackInSlot(i).copy();
if(stack.isEmpty()) continue; if(stack.isEmpty()) continue;
for(SlotRange range:ranges) { for(InventoryRange range:ranges) {
ItemStack remaining = range.insert(stack, false, limit); ItemStack remaining = range.insert(stack, false, limit, false, false);
if(remaining.getCount() < stack.getCount()) changed = true; if(remaining.getCount() < stack.getCount()) changed = true;
boolean stop = (remaining.getCount() <= Math.max(0, (stack.getCount()-limit))); boolean stop = (remaining.getCount() <= Math.max(0, (stack.getCount()-limit)));
stack = remaining; stack = remaining;
if(stop) break; if(stop) break;
} }
inventory_.setInventorySlotContents(i+CRAFTING_SLOTS_BEGIN, stack.isEmpty() ? ItemStack.EMPTY : stack); crafting_grid_range_.setInventorySlotContents(i, stack.isEmpty() ? ItemStack.EMPTY : stack);
} }
return changed; return changed;
} }
private boolean increase_grid_stacks(SlotRange[] ranges, int limit) private boolean increase_grid_stacks(InventoryRange[] ranges, int limit)
{ return place_stacks(ranges, incr_crafting_grid_stacks(limit)) != PlacementResult.UNCHANGED; } { return place_stacks(ranges, incr_crafting_grid_stacks(limit)) != PlacementResult.UNCHANGED; }
} }
@ -1259,6 +1248,12 @@ public class EdCraftingTable
nbt.putInt("containerslot", slotId); nbt.putInt("containerslot", slotId);
action(CraftingTableContainer.ACTION_MOVE_ALL_STACKS, nbt); action(CraftingTableContainer.ACTION_MOVE_ALL_STACKS, nbt);
return; return;
} else if((slotId > 0) && (slotId <= 9)) {
// Move from grid to storage or player inventory
CompoundNBT nbt = new CompoundNBT();
nbt.putInt("containerslot", slotId);
action(CraftingTableContainer.ACTION_MOVE_STACK, nbt);
return;
} else { } else {
// Let the normal slot click handle that. // Let the normal slot click handle that.
} }
@ -1539,7 +1534,7 @@ public class EdCraftingTable
final IRecipe recipe = ((CraftResultInventory)this.inventory).getRecipeUsed(); final IRecipe recipe = ((CraftResultInventory)this.inventory).getRecipeUsed();
final ArrayList<ItemStack> grid = new ArrayList<ItemStack>(); final ArrayList<ItemStack> grid = new ArrayList<ItemStack>();
grid.add(stack); grid.add(stack);
for(int i = 0; i < 9; ++i) grid.add(container.inventory_.getStackInSlot(i)); for(int i = 0; i<9; ++i) grid.add(container.inventory_.getStackInSlot(i));
if(recipe instanceof ICraftingRecipe) { if(recipe instanceof ICraftingRecipe) {
container.history().add(grid, (ICraftingRecipe)recipe); container.history().add(grid, (ICraftingRecipe)recipe);
container.history().reset_current(); container.history().reset_current();

View file

@ -8,15 +8,8 @@
*/ */
package wile.engineersdecor.blocks; package wile.engineersdecor.blocks;
import com.mojang.blaze3d.matrix.MatrixStack; import net.minecraft.inventory.container.ClickType;
import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3d;
import wile.engineersdecor.ModContent;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.libmc.detail.Inventories;
import wile.engineersdecor.libmc.detail.Inventories.SlotRange;
import wile.engineersdecor.libmc.detail.Networking;
import wile.engineersdecor.libmc.detail.TooltipDisplay;
import wile.engineersdecor.libmc.detail.TooltipDisplay.TipRange;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.state.BooleanProperty; import net.minecraft.state.BooleanProperty;
@ -57,6 +50,15 @@ import net.minecraftforge.items.wrapper.SidedInvWrapper;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.matrix.MatrixStack;
import wile.engineersdecor.ModContent;
import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.libmc.detail.Auxiliaries;
import wile.engineersdecor.libmc.detail.Inventories;
import wile.engineersdecor.libmc.detail.Inventories.InventoryRange;
import wile.engineersdecor.libmc.detail.Networking;
import wile.engineersdecor.libmc.detail.TooltipDisplay;
import wile.engineersdecor.libmc.detail.TooltipDisplay.TipRange;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
@ -240,7 +242,7 @@ public class EdDropper
private int drop_slot_index_ = 0; private int drop_slot_index_ = 0;
private int tick_timer_ = 0; private int tick_timer_ = 0;
protected NonNullList<ItemStack> stacks_; protected NonNullList<ItemStack> stacks_;
protected final SlotRange slot_range_ = new SlotRange(this, INPUT_SLOTS_FIRST, INPUT_SLOTS_FIRST+INPUT_SLOTS_SIZE); protected final InventoryRange storage_slot_range_;
public static void on_config(int cooldown_ticks) public static void on_config(int cooldown_ticks)
{ {
@ -254,6 +256,7 @@ public class EdDropper
{ {
super(te_type); super(te_type);
stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY); stacks_ = NonNullList.<ItemStack>withSize(NUM_OF_SLOTS, ItemStack.EMPTY);
storage_slot_range_ = new InventoryRange(this, INPUT_SLOTS_FIRST, INPUT_SLOTS_SIZE);
reset_rtstate(); reset_rtstate();
} }
@ -711,7 +714,7 @@ public class EdDropper
final boolean dropped = res.getA(); final boolean dropped = res.getA();
final List<ItemStack> remaining = res.getB(); final List<ItemStack> remaining = res.getB();
for(ItemStack st:remaining) { for(ItemStack st:remaining) {
if(!slot_range_.insert(st).isEmpty()) ModEngineersDecor.logger().debug("NOT ALL NON-DROPPED ITEMS PUT BACK:" + st); if(!storage_slot_range_.insert(st).isEmpty()) ModEngineersDecor.logger().debug("NOT ALL NON-DROPPED ITEMS PUT BACK:" + st);
} }
if(dropped || (!remaining.isEmpty())) dirty = true; if(dropped || (!remaining.isEmpty())) dirty = true;
// cooldown // cooldown
@ -737,11 +740,14 @@ public class EdDropper
public static class DropperContainer extends Container implements Networking.INetworkSynchronisableContainer public static class DropperContainer extends Container implements Networking.INetworkSynchronisableContainer
{ {
protected static final String QUICK_MOVE_ALL = "quick-move-all";
private static final int PLAYER_INV_START_SLOTNO = DropperTileEntity.NUM_OF_SLOTS; private static final int PLAYER_INV_START_SLOTNO = DropperTileEntity.NUM_OF_SLOTS;
private final PlayerEntity player_; private final PlayerEntity player_;
private final IInventory inventory_; private final IInventory inventory_;
private final IWorldPosCallable wpc_; private final IWorldPosCallable wpc_;
private final IIntArray fields_; private final IIntArray fields_;
private final InventoryRange player_inventory_range_;
private final InventoryRange block_storage_range_;
public final int field(int index) { return fields_.get(index); } public final int field(int index) { return fields_.get(index); }
@ -755,6 +761,8 @@ public class EdDropper
wpc_ = wpc; wpc_ = wpc;
player_ = player_inventory.player; player_ = player_inventory.player;
inventory_ = block_inventory; inventory_ = block_inventory;
block_storage_range_ = new InventoryRange(inventory_, 0, DropperTileEntity.NUM_OF_SLOTS);
player_inventory_range_ = InventoryRange.fromPlayerInventory(player_);
int i=-1; int i=-1;
// input slots (stacks 0 to 11) // input slots (stacks 0 to 11)
for(int y=0; y<2; ++y) { for(int y=0; y<2; ++y) {
@ -824,6 +832,13 @@ public class EdDropper
Networking.PacketContainerSyncClientToServer.sendToServer(windowId, nbt); Networking.PacketContainerSyncClientToServer.sendToServer(windowId, nbt);
} }
@OnlyIn(Dist.CLIENT)
public void onGuiAction(String message, CompoundNBT nbt)
{
nbt.putString("action", message);
Networking.PacketContainerSyncClientToServer.sendToServer(windowId, nbt);
}
@Override @Override
public void onServerPacketReceived(int windowId, CompoundNBT nbt) public void onServerPacketReceived(int windowId, CompoundNBT nbt)
{} {}
@ -832,16 +847,35 @@ public class EdDropper
public void onClientPacketReceived(int windowId, PlayerEntity player, CompoundNBT nbt) public void onClientPacketReceived(int windowId, PlayerEntity player, CompoundNBT nbt)
{ {
if(!(inventory_ instanceof DropperTileEntity)) return; if(!(inventory_ instanceof DropperTileEntity)) return;
DropperTileEntity te = (DropperTileEntity)inventory_; if(nbt.contains("action")) {
if(nbt.contains("drop_speed")) te.drop_speed_ = MathHelper.clamp(nbt.getInt("drop_speed"), 0, 100); boolean changed = false;
if(nbt.contains("drop_xdev")) te.drop_xdev_ = MathHelper.clamp(nbt.getInt("drop_xdev"), -100, 100); final int slotId = nbt.contains("slot") ? nbt.getInt("slot") : -1;
if(nbt.contains("drop_ydev")) te.drop_ydev_ = MathHelper.clamp(nbt.getInt("drop_ydev"), -100, 100); switch(nbt.getString("action")) {
if(nbt.contains("drop_count")) te.drop_count_ = MathHelper.clamp(nbt.getInt("drop_count"), 1, DropperTileEntity.MAX_DROP_COUNT); case QUICK_MOVE_ALL: {
if(nbt.contains("drop_period")) te.drop_period_ = MathHelper.clamp(nbt.getInt("drop_period"), 0, 100); if((slotId >= 0) && (slotId < PLAYER_INV_START_SLOTNO) && (getSlot(slotId).getHasStack())) {
if(nbt.contains("drop_logic")) te.drop_logic_ = nbt.getInt("drop_logic"); changed = block_storage_range_.move(getSlot(slotId).getSlotIndex(), player_inventory_range_, true, false, true, true);
if(nbt.contains("manual_rstrigger") && (nbt.getInt("manual_rstrigger")!=0)) { te.block_power_signal_=true; te.block_power_updated_=true; te.tick_timer_=1; } } else if((slotId >= PLAYER_INV_START_SLOTNO) && (slotId < PLAYER_INV_START_SLOTNO+36) && (getSlot(slotId).getHasStack())) {
if(nbt.contains("manual_trigger") && (nbt.getInt("manual_trigger")!=0)) { te.tick_timer_ = 1; te.triggered_ = true; } changed = player_inventory_range_.move(getSlot(slotId).getSlotIndex(), block_storage_range_, true, false, false, true);
te.markDirty(); }
} break;
}
if(changed) {
inventory_.markDirty();
player.inventory.markDirty();
detectAndSendChanges();
}
} else {
DropperTileEntity te = (DropperTileEntity)inventory_;
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);
if(nbt.contains("drop_count")) te.drop_count_ = MathHelper.clamp(nbt.getInt("drop_count"), 1, DropperTileEntity.MAX_DROP_COUNT);
if(nbt.contains("drop_period")) te.drop_period_ = MathHelper.clamp(nbt.getInt("drop_period"), 0, 100);
if(nbt.contains("drop_logic")) te.drop_logic_ = nbt.getInt("drop_logic");
if(nbt.contains("manual_rstrigger") && (nbt.getInt("manual_rstrigger")!=0)) { te.block_power_signal_=true; te.block_power_updated_=true; te.tick_timer_=1; }
if(nbt.contains("manual_trigger") && (nbt.getInt("manual_trigger")!=0)) { te.tick_timer_ = 1; te.triggered_ = true; }
te.markDirty();
}
} }
} }
@ -944,6 +978,19 @@ public class EdDropper
return true; return true;
} }
@Override
protected void handleMouseClick(Slot slot, int slotId, int button, ClickType type)
{
tooltip_.resetTimer();
if((type == ClickType.QUICK_MOVE) && (slot!=null) && slot.getHasStack() && Auxiliaries.isShiftDown() && Auxiliaries.isCtrlDown()) {
CompoundNBT nbt = new CompoundNBT();
nbt.putInt("slot", slotId);
container.onGuiAction(DropperContainer.QUICK_MOVE_ALL, nbt);
} else {
super.handleMouseClick(slot, slotId, button, type);
}
}
@Override @Override
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
protected void drawGuiContainerBackgroundLayer(MatrixStack mx, float partialTicks, int mouseX, int mouseY) protected void drawGuiContainerBackgroundLayer(MatrixStack mx, float partialTicks, int mouseX, int mouseY)

View file

@ -110,7 +110,6 @@ public class EdElectricalFurnace
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void animateTick(BlockState state, World world, BlockPos pos, Random rnd) public void animateTick(BlockState state, World world, BlockPos pos, Random rnd)
{} {}
} }
//-------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------
@ -136,7 +135,7 @@ public class EdElectricalFurnace
public static final int FIFO_INPUT_1_SLOT_NO = 4; 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_0_SLOT_NO = 5;
public static final int FIFO_OUTPUT_1_SLOT_NO = 6; public static final int FIFO_OUTPUT_1_SLOT_NO = 6;
public static final int DEFAULT_SPEED_PERCENT = 200; public static final int DEFAULT_SPEED_PERCENT = 250;
public static final int DEFAULT_ENERGY_CONSUMPTION = 16; 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; public static final int DEFAULT_SCALED_ENERGY_CONSUMPTION = DEFAULT_ENERGY_CONSUMPTION * HEAT_INCREMENT * DEFAULT_SPEED_PERCENT / 100;

View file

@ -586,7 +586,10 @@ public class EdFurnace
} }
if(burning() && canSmeltCurrentItem()) { if(burning() && canSmeltCurrentItem()) {
proc_time_elapsed_ += TICK_INTERVAL * proc_speed_; proc_time_elapsed_ += TICK_INTERVAL * proc_speed_;
if(heater_inserted_ && (boost_energy_ >= boost_energy_consumption)) { boost_energy_ = 0; proc_time_elapsed_ += TICK_INTERVAL; } if(heater_inserted_ && (boost_energy_ >= boost_energy_consumption)) {
boost_energy_ = 0;
proc_time_elapsed_ += (TICK_INTERVAL * proc_speed_)*2;
}
if(proc_time_elapsed_ >= proc_time_needed_) { if(proc_time_elapsed_ >= proc_time_needed_) {
proc_time_elapsed_ = 0; proc_time_elapsed_ = 0;
proc_time_needed_ = getSmeltingTimeNeeded(world, stacks_.get(SMELTING_INPUT_SLOT_NO)); proc_time_needed_ = getSmeltingTimeNeeded(world, stacks_.get(SMELTING_INPUT_SLOT_NO));

View file

@ -52,7 +52,7 @@ import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.libmc.detail.Auxiliaries; import wile.engineersdecor.libmc.detail.Auxiliaries;
import wile.engineersdecor.libmc.detail.Inventories; import wile.engineersdecor.libmc.detail.Inventories;
import wile.engineersdecor.libmc.detail.Networking; import wile.engineersdecor.libmc.detail.Networking;
import wile.engineersdecor.libmc.detail.Inventories.SlotRange; import wile.engineersdecor.libmc.detail.Inventories.InventoryRange;
import wile.engineersdecor.libmc.detail.TooltipDisplay; import wile.engineersdecor.libmc.detail.TooltipDisplay;
import wile.engineersdecor.libmc.detail.TooltipDisplay.TipRange; import wile.engineersdecor.libmc.detail.TooltipDisplay.TipRange;
@ -703,8 +703,8 @@ public class EdHopper
protected static final int STORAGE_SLOT_END = HopperTileEntity.NUM_OF_SLOTS; protected static final int STORAGE_SLOT_END = HopperTileEntity.NUM_OF_SLOTS;
protected static final int PLAYER_SLOT_BEGIN = HopperTileEntity.NUM_OF_SLOTS; protected static final int PLAYER_SLOT_BEGIN = HopperTileEntity.NUM_OF_SLOTS;
protected static final int PLAYER_SLOT_END = HopperTileEntity.NUM_OF_SLOTS+36; protected static final int PLAYER_SLOT_END = HopperTileEntity.NUM_OF_SLOTS+36;
private final SlotRange player_inventory_slot_range; private final InventoryRange player_inventory_range_;
private final SlotRange hopper_slot_range; private final InventoryRange block_storage_range_;
private final PlayerEntity player_; private final PlayerEntity player_;
private final IInventory inventory_; private final IInventory inventory_;
private final IWorldPosCallable wpc_; private final IWorldPosCallable wpc_;
@ -722,8 +722,8 @@ public class EdHopper
wpc_ = wpc; wpc_ = wpc;
player_ = player_inventory.player; player_ = player_inventory.player;
inventory_ = block_inventory; inventory_ = block_inventory;
hopper_slot_range = new SlotRange(inventory_, 0, HopperTileEntity.NUM_OF_SLOTS); block_storage_range_ = new InventoryRange(inventory_, 0, HopperTileEntity.NUM_OF_SLOTS);
player_inventory_slot_range = new SlotRange(player_inventory, 0, 36); player_inventory_range_ = InventoryRange.fromPlayerInventory(player_);
int i=-1; int i=-1;
// input slots (stacks 0 to 17) // input slots (stacks 0 to 17)
for(int y=0; y<3; ++y) { for(int y=0; y<3; ++y) {
@ -816,35 +816,10 @@ public class EdHopper
switch(nbt.getString("action")) { switch(nbt.getString("action")) {
case QUICK_MOVE_ALL: { case QUICK_MOVE_ALL: {
if((slotId >= STORAGE_SLOT_BEGIN) && (slotId < STORAGE_SLOT_END) && (getSlot(slotId).getHasStack())) { if((slotId >= STORAGE_SLOT_BEGIN) && (slotId < STORAGE_SLOT_END) && (getSlot(slotId).getHasStack())) {
final Slot slot = getSlot(slotId); changed = block_storage_range_.move(getSlot(slotId).getSlotIndex(), player_inventory_range_, true, false, true, true);
ItemStack remaining = slot.getStack();
slot.putStack(ItemStack.EMPTY);
final ItemStack ref_stack = remaining.copy();
ref_stack.setCount(ref_stack.getMaxStackSize());
for(int i=hopper_slot_range.end_slot-hopper_slot_range.start_slot; (i>0) && (!remaining.isEmpty()); --i) {
remaining = player_inventory_slot_range.insert(remaining, false, 0, true, true);
if(!remaining.isEmpty()) break;
remaining = hopper_slot_range.extract(ref_stack);
}
if(!remaining.isEmpty()) {
slot.putStack(remaining); // put back
}
} else if((slotId >= PLAYER_SLOT_BEGIN) && (slotId < PLAYER_SLOT_END) && (getSlot(slotId).getHasStack())) { } else if((slotId >= PLAYER_SLOT_BEGIN) && (slotId < PLAYER_SLOT_END) && (getSlot(slotId).getHasStack())) {
final Slot slot = getSlot(slotId); changed = player_inventory_range_.move(getSlot(slotId).getSlotIndex(), block_storage_range_, true, false, false, true);
ItemStack remaining = slot.getStack();
slot.putStack(ItemStack.EMPTY);
final ItemStack ref_stack = remaining.copy();
ref_stack.setCount(ref_stack.getMaxStackSize());
for(int i=player_inventory_slot_range.end_slot-player_inventory_slot_range.start_slot; (i>0) && (!remaining.isEmpty()); --i) {
remaining = hopper_slot_range.insert(remaining, false, 0, false, true);
if(!remaining.isEmpty()) break;
remaining = player_inventory_slot_range.extract(ref_stack);
}
if(!remaining.isEmpty()) {
slot.putStack(remaining); // put back
}
} }
changed = true;
} break; } break;
} }
if(changed) { if(changed) {
@ -855,7 +830,6 @@ public class EdHopper
} }
te.markDirty(); te.markDirty();
} }
} }
//-------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------

View file

@ -13,7 +13,6 @@ import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.libmc.blocks.StandardBlocks; import wile.engineersdecor.libmc.blocks.StandardBlocks;
import wile.engineersdecor.libmc.detail.Auxiliaries; import wile.engineersdecor.libmc.detail.Auxiliaries;
import wile.engineersdecor.libmc.detail.Inventories.InventoryRange; import wile.engineersdecor.libmc.detail.Inventories.InventoryRange;
import wile.engineersdecor.libmc.detail.Inventories.SlotRange;
import wile.engineersdecor.libmc.detail.Networking; import wile.engineersdecor.libmc.detail.Networking;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.server.ServerWorld; import net.minecraft.world.server.ServerWorld;
@ -571,8 +570,9 @@ public class EdLabeledCrate
protected final IInventory inventory_; protected final IInventory inventory_;
protected final IWorldPosCallable wpc_; protected final IWorldPosCallable wpc_;
private final IIntArray fields_; private final IIntArray fields_;
private final SlotRange player_inventory_slot_range; private final InventoryRange player_inventory_range_;
private final SlotRange crate_slot_range; private final InventoryRange block_storage_range_;
private final InventoryRange frame_slot_range_;
//------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------
public int field(int index) { return fields_.get(index); } public int field(int index) { return fields_.get(index); }
public PlayerEntity player() { return player_ ; } public PlayerEntity player() { return player_ ; }
@ -590,8 +590,9 @@ public class EdLabeledCrate
inventory_ = block_inventory; inventory_ = block_inventory;
wpc_ = wpc; wpc_ = wpc;
fields_ = fields; fields_ = fields;
crate_slot_range = new SlotRange(inventory_, 0, LabeledCrateTileEntity.ITEMFRAME_SLOTNO); block_storage_range_ = new InventoryRange(inventory_, 0, LabeledCrateTileEntity.ITEMFRAME_SLOTNO);
player_inventory_slot_range = new SlotRange(player_inventory, 0, 36); player_inventory_range_ = new InventoryRange(player_inventory, 0, 36);
frame_slot_range_ = new InventoryRange(inventory_, 54, 1);
int i=-1; int i=-1;
// storage slots (stacks 0 to 53) // storage slots (stacks 0 to 53)
for(int y=0; y<6; ++y) { for(int y=0; y<6; ++y) {
@ -601,9 +602,7 @@ public class EdLabeledCrate
} }
} }
// picture frame slot (54) // picture frame slot (54)
addSlot(new Slot(new InventoryRange(inventory_, 54, 1), 0, 191, 100) { addSlot(new Slot(frame_slot_range_, 0, 191, 100) { @Override public int getSlotStackLimit(){return 1;} });
@Override public int getSlotStackLimit(){return 1;}
});
// player slots // player slots
for(int x=0; x<9; ++x) { for(int x=0; x<9; ++x) {
addSlot(new Slot(player_inventory, x, 28+x*18, 183)); // player slots: 0..8 addSlot(new Slot(player_inventory, x, 28+x*18, 183)); // player slots: 0..8
@ -676,35 +675,10 @@ public class EdLabeledCrate
switch(nbt.getString("action")) { switch(nbt.getString("action")) {
case QUICK_MOVE_ALL: { case QUICK_MOVE_ALL: {
if((slotId >= STORAGE_SLOT_BEGIN) && (slotId < STORAGE_SLOT_END) && (getSlot(slotId).getHasStack())) { if((slotId >= STORAGE_SLOT_BEGIN) && (slotId < STORAGE_SLOT_END) && (getSlot(slotId).getHasStack())) {
final Slot slot = getSlot(slotId); changed = block_storage_range_.move(getSlot(slotId).getSlotIndex(), player_inventory_range_, true, false, true, true);
ItemStack remaining = slot.getStack();
slot.putStack(ItemStack.EMPTY);
final ItemStack ref_stack = remaining.copy();
ref_stack.setCount(ref_stack.getMaxStackSize());
for(int i=crate_slot_range.end_slot-crate_slot_range.start_slot; (i>0) && (!remaining.isEmpty()); --i) {
remaining = player_inventory_slot_range.insert(remaining, false, 0, true, true);
if(!remaining.isEmpty()) break;
remaining = crate_slot_range.extract(ref_stack);
}
if(!remaining.isEmpty()) {
slot.putStack(remaining); // put back
}
} else if((slotId >= PLAYER_SLOT_BEGIN) && (slotId < PLAYER_SLOT_END) && (getSlot(slotId).getHasStack())) { } else if((slotId >= PLAYER_SLOT_BEGIN) && (slotId < PLAYER_SLOT_END) && (getSlot(slotId).getHasStack())) {
final Slot slot = getSlot(slotId); changed = player_inventory_range_.move(getSlot(slotId).getSlotIndex(), block_storage_range_, true, false, false, true);
ItemStack remaining = slot.getStack();
slot.putStack(ItemStack.EMPTY);
final ItemStack ref_stack = remaining.copy();
ref_stack.setCount(ref_stack.getMaxStackSize());
for(int i=player_inventory_slot_range.end_slot-player_inventory_slot_range.start_slot; (i>0) && (!remaining.isEmpty()); --i) {
remaining = crate_slot_range.insert(remaining, false, 0, false, true);
if(!remaining.isEmpty()) break;
remaining = player_inventory_slot_range.extract(ref_stack);
}
if(!remaining.isEmpty()) {
slot.putStack(remaining); // put back
}
} }
changed = true;
} break; } break;
case INCREASE_STACK: { case INCREASE_STACK: {
} break; } break;

View file

@ -9,9 +9,12 @@
package wile.engineersdecor.blocks; package wile.engineersdecor.blocks;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.inventory.container.ClickType;
import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3d;
import wile.engineersdecor.ModContent; import wile.engineersdecor.ModContent;
import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.ModEngineersDecor;
import wile.engineersdecor.libmc.detail.Auxiliaries;
import wile.engineersdecor.libmc.detail.Inventories.InventoryRange;
import wile.engineersdecor.libmc.detail.Networking; import wile.engineersdecor.libmc.detail.Networking;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
@ -600,11 +603,14 @@ public class EdPlacer
public static class PlacerContainer extends Container implements Networking.INetworkSynchronisableContainer public static class PlacerContainer extends Container implements Networking.INetworkSynchronisableContainer
{ {
protected static final String QUICK_MOVE_ALL = "quick-move-all";
private static final int PLAYER_INV_START_SLOTNO = PlacerTileEntity.NUM_OF_SLOTS; private static final int PLAYER_INV_START_SLOTNO = PlacerTileEntity.NUM_OF_SLOTS;
private final PlayerEntity player_; private final PlayerEntity player_;
private final IInventory inventory_; private final IInventory inventory_;
private final IWorldPosCallable wpc_; private final IWorldPosCallable wpc_;
private final IIntArray fields_; private final IIntArray fields_;
private final InventoryRange player_inventory_range_;
private final InventoryRange block_storage_range_;
public final int field(int index) { return fields_.get(index); } public final int field(int index) { return fields_.get(index); }
@ -618,6 +624,8 @@ public class EdPlacer
wpc_ = wpc; wpc_ = wpc;
player_ = player_inventory.player; player_ = player_inventory.player;
inventory_ = block_inventory; inventory_ = block_inventory;
block_storage_range_ = new InventoryRange(inventory_, 0, PlacerTileEntity.NUM_OF_SLOTS);
player_inventory_range_ = InventoryRange.fromPlayerInventory(player_);
int i=-1; int i=-1;
// device slots (stacks 0 to 17) // device slots (stacks 0 to 17)
for(int y=0; y<3; ++y) { for(int y=0; y<3; ++y) {
@ -683,6 +691,13 @@ public class EdPlacer
Networking.PacketContainerSyncClientToServer.sendToServer(windowId, nbt); Networking.PacketContainerSyncClientToServer.sendToServer(windowId, nbt);
} }
@OnlyIn(Dist.CLIENT)
public void onGuiAction(String message, CompoundNBT nbt)
{
nbt.putString("action", message);
Networking.PacketContainerSyncClientToServer.sendToServer(windowId, nbt);
}
@Override @Override
public void onServerPacketReceived(int windowId, CompoundNBT nbt) public void onServerPacketReceived(int windowId, CompoundNBT nbt)
{} {}
@ -691,10 +706,30 @@ public class EdPlacer
public void onClientPacketReceived(int windowId, PlayerEntity player, CompoundNBT nbt) public void onClientPacketReceived(int windowId, PlayerEntity player, CompoundNBT nbt)
{ {
if(!(inventory_ instanceof PlacerTileEntity)) return; if(!(inventory_ instanceof PlacerTileEntity)) return;
PlacerTileEntity te = (PlacerTileEntity)inventory_; if(nbt.contains("action")) {
if(nbt.contains("logic")) te.logic_ = nbt.getInt("logic"); boolean changed = false;
if(nbt.contains("manual_trigger") && (nbt.getInt("manual_trigger")!=0)) { te.block_power_signal_=true; te.block_power_updated_=true; te.tick_timer_=1; } final int slotId = nbt.contains("slot") ? nbt.getInt("slot") : -1;
te.markDirty(); switch(nbt.getString("action")) {
case QUICK_MOVE_ALL: {
if((slotId >= 0) && (slotId < PLAYER_INV_START_SLOTNO) && (getSlot(slotId).getHasStack())) {
changed = block_storage_range_.move(getSlot(slotId).getSlotIndex(), player_inventory_range_, true, false, true, true);
} else if((slotId >= PLAYER_INV_START_SLOTNO) && (slotId < PLAYER_INV_START_SLOTNO+36) && (getSlot(slotId).getHasStack())) {
changed = player_inventory_range_.move(getSlot(slotId).getSlotIndex(), block_storage_range_, true, false, false, true);
}
} break;
}
if(changed) {
inventory_.markDirty();
player.inventory.markDirty();
detectAndSendChanges();
}
} else {
PlacerTileEntity te = (PlacerTileEntity)inventory_;
if(nbt.contains("logic")) te.logic_ = nbt.getInt("logic");
if(nbt.contains("manual_trigger") && (nbt.getInt("manual_trigger")!=0)) { te.block_power_signal_=true; te.block_power_updated_=true; te.tick_timer_=1; }
te.markDirty();
}
} }
} }
@ -756,6 +791,19 @@ public class EdPlacer
return true; return true;
} }
@Override
protected void handleMouseClick(Slot slot, int slotId, int button, ClickType type)
{
tooltip_.resetTimer();
if((type == ClickType.QUICK_MOVE) && (slot!=null) && slot.getHasStack() && Auxiliaries.isShiftDown() && Auxiliaries.isCtrlDown()) {
CompoundNBT nbt = new CompoundNBT();
nbt.putInt("slot", slotId);
container.onGuiAction(PlacerContainer.QUICK_MOVE_ALL, nbt);
} else {
super.handleMouseClick(slot, slotId, button, type);
}
}
@Override @Override
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
protected void drawGuiContainerBackgroundLayer/*drawGuiContainerBackgroundLayer*/(MatrixStack mx, float partialTicks, int mouseX, int mouseY) protected void drawGuiContainerBackgroundLayer/*drawGuiContainerBackgroundLayer*/(MatrixStack mx, float partialTicks, int mouseX, int mouseY)

View file

@ -14,7 +14,7 @@ import net.minecraftforge.registries.ObjectHolder;
public class ExternalObjects public class ExternalObjects
{ {
@ObjectHolder("immersiveengineering:external_heater") @ObjectHolder("immersiveengineering:furnace_heater")
public static final Item IE_EXTERNAL_HEATER = null; public static final Item IE_EXTERNAL_HEATER = null;
@ObjectHolder("bottledmilk:milk_bottle_drinkable") @ObjectHolder("bottledmilk:milk_bottle_drinkable")

View file

@ -18,6 +18,7 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.inventory.IInventory; import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ISidedInventory; import net.minecraft.inventory.ISidedInventory;
@ -33,7 +34,6 @@ import java.util.List;
public class Inventories public class Inventories
{ {
public static boolean areItemStacksIdentical(ItemStack a, ItemStack b) public static boolean areItemStacksIdentical(ItemStack a, ItemStack b)
{ return (a.getItem()==b.getItem()) && ItemStack.areItemStackTagsEqual(a, b); } { return (a.getItem()==b.getItem()) && ItemStack.areItemStackTagsEqual(a, b); }
@ -98,190 +98,46 @@ public class Inventories
} }
private static ItemStack checked(ItemStack stack) private static ItemStack checked(ItemStack stack)
{ return stack.isEmpty() ? ItemStack.EMPTY : stack; } // explicit EMPTY return { return stack.isEmpty() ? ItemStack.EMPTY : stack; }
//-------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------
public static class SlotRange public static ItemStack insert(InventoryRange to_ranges[], ItemStack stack)
{ {
public final IInventory inventory; ItemStack remaining = stack.copy();
public final int start_slot, end_slot; for(InventoryRange range:to_ranges) {
remaining = range.insert(remaining, false, 0, false, true);
public SlotRange(IInventory inv, int start, int end) if(remaining.isEmpty()) return remaining;
{ inventory=inv; start_slot=start; end_slot=end; }
/**
* Returns the number of stacks that match the given stack with NBT.
*/
public int stackMatchCount(final ItemStack ref_stack)
{
int n = 0; // ... std::accumulate() the old school way.
for(int i = start_slot; i < end_slot; ++i) {
if(areItemStacksIdentical(ref_stack, inventory.getStackInSlot(i))) ++n;
}
return n;
}
public int totalMatchingItemCount(final ItemStack ref_stack)
{
int n = 0;
for(int i = start_slot; i < end_slot; ++i) {
ItemStack stack = inventory.getStackInSlot(i);
if(areItemStacksIdentical(ref_stack, stack)) n += stack.getCount();
}
return n;
}
/**
* Moves as much items from the stack to the slots in range [start_slot, end_slot] of the inventory,
* filling up existing stacks first, then (player inventory only) checks appropriate empty slots next
* to stacks that have that item already, and last uses any empty slot that can be found.
* Returns the stack that is still remaining in the referenced `stack`.
*/
public ItemStack insert(final ItemStack stack_to_move, boolean only_fillup, int limit, boolean reverse, boolean force_group_stacks)
{
final ItemStack mvstack = stack_to_move.copy();
if((mvstack.isEmpty()) || (start_slot < 0) || (end_slot > inventory.getSizeInventory())) return checked(mvstack);
int limit_left = (limit>0) ? (Math.min(limit, mvstack.getMaxStackSize())) : (mvstack.getMaxStackSize());
boolean matches[] = new boolean[end_slot];
boolean empties[] = new boolean[end_slot];
int num_matches = 0;
for(int i = start_slot; i < end_slot; ++i) {
final int sno = reverse ? (end_slot-1-i) : (i);
final ItemStack stack = inventory.getStackInSlot(sno);
if(stack.isEmpty()) {
empties[sno] = true;
} else if(areItemStacksIdentical(stack, mvstack)) {
matches[sno] = true;
++num_matches;
}
}
// first iteration: fillup existing stacks
for(int i = start_slot; i < end_slot; ++i) {
final int sno = reverse ? (end_slot-1-i) : (i);
if((empties[sno]) || (!matches[sno])) continue;
final ItemStack stack = inventory.getStackInSlot(sno);
int nmax = Math.min(limit_left, stack.getMaxStackSize() - stack.getCount());
if(mvstack.getCount() <= nmax) {
stack.setCount(stack.getCount()+mvstack.getCount());
inventory.setInventorySlotContents(sno, stack);
return ItemStack.EMPTY;
} else {
stack.grow(nmax);
mvstack.shrink(nmax);
inventory.setInventorySlotContents(sno, stack);
limit_left -= nmax;
}
}
if(only_fillup) return checked(mvstack);
if((num_matches>0) && ((force_group_stacks) || (inventory instanceof PlayerInventory))) {
// second iteration: use appropriate empty slots,
// a) between
{
int insert_start = -1;
int insert_end = -1;
int i = start_slot+1;
for(;i < end_slot-1; ++i) {
final int sno = reverse ? (end_slot-1-i) : (i);
if(insert_start < 0) {
if(matches[sno]) insert_start = sno;
} else if(matches[sno]) {
insert_end = sno;
}
}
for(i=insert_start;i < insert_end; ++i) {
final int sno = reverse ? (end_slot-1-i) : (i);
if((!empties[sno]) || (!inventory.isItemValidForSlot(sno, mvstack))) continue;
int nmax = Math.min(limit_left, mvstack.getCount());
ItemStack moved = mvstack.copy();
moved.setCount(nmax);
mvstack.shrink(nmax);
inventory.setInventorySlotContents(sno, moved);
return checked(mvstack);
}
}
// b) before/after
{
for(int i = start_slot+1; i < end_slot-1; ++i) {
final int sno = reverse ? (end_slot-1-i) : (i);
if(!matches[sno]) continue;
int ii = (empties[sno-1]) ? (sno-1) : (empties[sno+1] ? (sno+1) : -1);
if((ii >= 0) && (inventory.isItemValidForSlot(ii, mvstack))) {
int nmax = Math.min(limit_left, mvstack.getCount());
ItemStack moved = mvstack.copy();
moved.setCount(nmax);
mvstack.shrink(nmax);
inventory.setInventorySlotContents(ii, moved);
return checked(mvstack);
}
}
}
}
// third iteration: use any empty slots
for(int i = start_slot; i < end_slot; ++i) {
final int sno = reverse ? (end_slot-1-i) : (i);
if((!empties[sno]) || (!inventory.isItemValidForSlot(sno, mvstack))) continue;
int nmax = Math.min(limit_left, mvstack.getCount());
ItemStack placed = mvstack.copy();
placed.setCount(nmax);
mvstack.shrink(nmax);
inventory.setInventorySlotContents(sno, placed);
return checked(mvstack);
}
return checked(mvstack);
}
public ItemStack insert(final ItemStack stack_to_move, boolean only_fillup, int limit)
{ return insert(stack_to_move, only_fillup, limit, false, false); }
public ItemStack insert(final ItemStack stack_to_move, boolean only_fillup)
{ return insert(stack_to_move, only_fillup, 0, false, false); }
public ItemStack insert(final ItemStack stack_to_move)
{ return insert(stack_to_move, false, 0, false, false); }
/**
* Moves as much items from the slots in range [start_slot, end_slot] of the inventory into a new stack.
* Implicitly shrinks the inventory stacks and the `request_stack`.
*/
public ItemStack extract(final ItemStack request_stack)
{
if(request_stack.isEmpty()) return ItemStack.EMPTY;
final IInventory inventory = this.inventory;
List<ItemStack> matches = new ArrayList<>();
for(int i = start_slot; i < end_slot; ++i) {
final ItemStack stack = inventory.getStackInSlot(i);
if((!stack.isEmpty()) && (areItemStacksIdentical(stack, request_stack))) {
if(stack.hasTag()) {
final CompoundNBT nbt = stack.getTag();
int n = nbt.size();
if((n > 0) && (nbt.contains("Damage"))) --n;
if(n > 0) continue;
}
matches.add(stack);
}
}
matches.sort((a,b) -> Integer.compare(a.getCount(), b.getCount()));
if(matches.isEmpty()) return ItemStack.EMPTY;
int n_left = request_stack.getCount();
ItemStack fetched_stack = matches.get(0).split(n_left);
n_left -= fetched_stack.getCount();
for(int i=1; (i<matches.size()) && (n_left>0); ++i) {
ItemStack stack = matches.get(i).split(n_left);
n_left -= stack.getCount();
fetched_stack.grow(stack.getCount());
}
return checked(fetched_stack);
} }
return remaining;
} }
public static class InventoryRange implements IInventory public static class InventoryRange implements IInventory
{ {
public final IInventory inventory; public final IInventory inventory;
public final int offset, size; public final int offset, size, num_rows;
public InventoryRange(IInventory inventory, int offset, int size, int num_rows)
{
this.inventory = inventory;
this.offset = MathHelper.clamp(offset, 0, inventory.getSizeInventory()-1);
this.size = MathHelper.clamp(size, 0, inventory.getSizeInventory()-this.offset);
this.num_rows = num_rows;
}
public InventoryRange(IInventory inventory, int offset, int size) public InventoryRange(IInventory inventory, int offset, int size)
{ this.inventory = inventory; this.offset = offset; this.size = size; } { this(inventory, offset, size, 1); }
public static InventoryRange fromPlayerHotbar(PlayerEntity player)
{ return new InventoryRange(player.inventory, 0, 9, 1); }
public static InventoryRange fromPlayerStorage(PlayerEntity player)
{ return new InventoryRange(player.inventory, 9, 27, 3); }
public static InventoryRange fromPlayerInventory(PlayerEntity player)
{ return new InventoryRange(player.inventory, 0, 36, 4); }
// IInventory ------------------------------------------------------------------------------------------------------
public void clear() public void clear()
{ inventory.clear(); } { inventory.clear(); }
@ -321,6 +177,213 @@ public class Inventories
public boolean isItemValidForSlot(int index, ItemStack stack) public boolean isItemValidForSlot(int index, ItemStack stack)
{ return inventory.isItemValidForSlot(offset+index, stack); } { return inventory.isItemValidForSlot(offset+index, stack); }
//------------------------------------------------------------------------------------------------------------------
/**
* Returns the number of stacks that match the given stack with NBT.
*/
public int stackMatchCount(final ItemStack ref_stack)
{
int n = 0; // ... std::accumulate() the old school way.
for(int i=0; i<size; ++i) {
if(areItemStacksIdentical(ref_stack, getStackInSlot(i))) ++n;
}
return n;
}
public int totalMatchingItemCount(final ItemStack ref_stack)
{
int n = 0;
for(int i=0; i<size; ++i) {
ItemStack stack = getStackInSlot(i);
if(areItemStacksIdentical(ref_stack, stack)) n += stack.getCount();
}
return n;
}
/**
* Moves as much items from the stack to the slots in range [offset, end_slot] of the inventory,
* filling up existing stacks first, then (player inventory only) checks appropriate empty slots next
* to stacks that have that item already, and last uses any empty slot that can be found.
* Returns the stack that is still remaining in the referenced `stack`.
*/
public ItemStack insert(final ItemStack input_stack, boolean only_fillup, int limit, boolean reverse, boolean force_group_stacks)
{
final ItemStack mvstack = input_stack.copy();
//final int end_slot = offset + size;
if(mvstack.isEmpty()) return checked(mvstack);
int limit_left = (limit>0) ? (Math.min(limit, mvstack.getMaxStackSize())) : (mvstack.getMaxStackSize());
boolean matches[] = new boolean[size];
boolean empties[] = new boolean[size];
int num_matches = 0;
for(int i=0; i < size; ++i) {
final int sno = reverse ? (size-1-i) : (i);
final ItemStack stack = getStackInSlot(sno);
if(stack.isEmpty()) {
empties[sno] = true;
} else if(areItemStacksIdentical(stack, mvstack)) {
matches[sno] = true;
++num_matches;
}
}
// first iteration: fillup existing stacks
for(int i=0; i<size; ++i) {
final int sno = reverse ? (size-1-i) : (i);
if((empties[sno]) || (!matches[sno])) continue;
final ItemStack stack = getStackInSlot(sno);
int nmax = Math.min(limit_left, stack.getMaxStackSize() - stack.getCount());
if(mvstack.getCount() <= nmax) {
stack.setCount(stack.getCount()+mvstack.getCount());
setInventorySlotContents(sno, stack);
return ItemStack.EMPTY;
} else {
stack.grow(nmax);
mvstack.shrink(nmax);
setInventorySlotContents(sno, stack);
limit_left -= nmax;
}
}
if(only_fillup) return checked(mvstack);
if((num_matches>0) && ((force_group_stacks) || (inventory instanceof PlayerInventory))) {
// second iteration: use appropriate empty slots,
// a) between
{
int insert_start = -1;
int insert_end = -1;
int i = 1;
for(;i<size-1; ++i) {
final int sno = reverse ? (size-1-i) : (i);
if(insert_start < 0) {
if(matches[sno]) insert_start = sno;
} else if(matches[sno]) {
insert_end = sno;
}
}
for(i=insert_start;i < insert_end; ++i) {
final int sno = reverse ? (size-1-i) : (i);
if((!empties[sno]) || (!isItemValidForSlot(sno, mvstack))) continue;
int nmax = Math.min(limit_left, mvstack.getCount());
ItemStack moved = mvstack.copy();
moved.setCount(nmax);
mvstack.shrink(nmax);
setInventorySlotContents(sno, moved);
return checked(mvstack);
}
}
// b) before/after
{
for(int i=1; i<size-1; ++i) {
final int sno = reverse ? (size-1-i) : (i);
if(!matches[sno]) continue;
int ii = (empties[sno-1]) ? (sno-1) : (empties[sno+1] ? (sno+1) : -1);
if((ii >= 0) && (isItemValidForSlot(ii, mvstack))) {
int nmax = Math.min(limit_left, mvstack.getCount());
ItemStack moved = mvstack.copy();
moved.setCount(nmax);
mvstack.shrink(nmax);
setInventorySlotContents(ii, moved);
return checked(mvstack);
}
}
}
}
// third iteration: use any empty slots
for(int i=0; i<size; ++i) {
final int sno = reverse ? (size-1-i) : (i);
if((!empties[sno]) || (!isItemValidForSlot(sno, mvstack))) continue;
int nmax = Math.min(limit_left, mvstack.getCount());
ItemStack placed = mvstack.copy();
placed.setCount(nmax);
mvstack.shrink(nmax);
setInventorySlotContents(sno, placed);
return checked(mvstack);
}
return checked(mvstack);
}
public ItemStack insert(final ItemStack stack_to_move)
{ return insert(stack_to_move, false, 0, false, true); }
/**
* Moves as much items from the slots in range [offset, end_slot] of the inventory into a new stack.
* Implicitly shrinks the inventory stacks and the `request_stack`.
*/
public ItemStack extract(final ItemStack request_stack)
{
if(request_stack.isEmpty()) return ItemStack.EMPTY;
List<ItemStack> matches = new ArrayList<>();
for(int i=0; i<size; ++i) {
final ItemStack stack = getStackInSlot(i);
if((!stack.isEmpty()) && (areItemStacksIdentical(stack, request_stack))) {
if(stack.hasTag()) {
final CompoundNBT nbt = stack.getTag();
int n = nbt.size();
if((n > 0) && (nbt.contains("Damage"))) --n;
if(n > 0) continue;
}
matches.add(stack);
}
}
matches.sort((a,b) -> Integer.compare(a.getCount(), b.getCount()));
if(matches.isEmpty()) return ItemStack.EMPTY;
int n_left = request_stack.getCount();
ItemStack fetched_stack = matches.get(0).split(n_left);
n_left -= fetched_stack.getCount();
for(int i=1; (i<matches.size()) && (n_left>0); ++i) {
ItemStack stack = matches.get(i).split(n_left);
n_left -= stack.getCount();
fetched_stack.grow(stack.getCount());
}
return checked(fetched_stack);
}
/**
* Moves items from this inventory range to another. Returns true if something was moved
* (if the inventories should be marked dirty).
*/
public boolean move(int index, final InventoryRange target_range, boolean all_identical_stacks, boolean only_fillup, boolean reverse, boolean force_group_stacks)
{
final ItemStack source_stack = getStackInSlot(index);
if(source_stack.isEmpty()) return false;
if(!all_identical_stacks) {
ItemStack remaining = target_range.insert(source_stack, only_fillup, 0, reverse, force_group_stacks);
setInventorySlotContents(index, remaining);
return (remaining.getCount() != source_stack.getCount());
} else {
ItemStack remaining = source_stack.copy();
setInventorySlotContents(index, ItemStack.EMPTY);
final ItemStack ref_stack = remaining.copy();
ref_stack.setCount(ref_stack.getMaxStackSize());
for(int i=size; (i>0) && (!remaining.isEmpty()); --i) {
remaining = target_range.insert(remaining, only_fillup, 0, reverse, force_group_stacks);
if(!remaining.isEmpty()) break;
remaining = this.extract(ref_stack);
}
if(!remaining.isEmpty()) {
setInventorySlotContents(index, remaining); // put back
}
return (remaining.getCount() != source_stack.getCount());
}
}
public boolean move(int index, final InventoryRange target_range)
{ return move(index, target_range, false, false, false, true); }
/**
* Moves/clears the complete range to another range if possible. Returns true if something was moved
* (if the inventories should be marked dirty).
*/
public boolean move(final InventoryRange target_range, boolean only_fillup, boolean reverse, boolean force_group_stacks)
{
boolean changed = false;
for(int i=0; i<size; ++i) changed |= move(i, target_range, false, only_fillup, reverse, force_group_stacks);
return changed;
}
public boolean move(final InventoryRange target_range)
{ return move(target_range, false, false, true); }
} }
//-------------------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------------------