Skip to content

Commit

Permalink
rewrite the chest sorting algorithm and bump version
Browse files Browse the repository at this point in the history
  • Loading branch information
rogerahuntley committed Jul 9, 2023
1 parent 84830e5 commit 62d3e75
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 93 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ loader_version=0.14.19-babric.1
halplibe_version=1.1.4

# Mod
mod_version=1.0.1
mod_version=1.0.2
mod_group=youngsditch
mod_name=ancientlogistics
157 changes: 67 additions & 90 deletions src/main/java/youngsditch/ancientlogistics/gears/GearChestSorter.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import net.minecraft.src.*;
import youngsditch.ancientlogistics.mixin.ChestAccessor;
Expand All @@ -16,10 +14,10 @@ public GearChestSorter(int id) {
}

class ChestWithDistance {
public final ChestAccessor chest;
public final TileEntityChest chest;
public final float distance;

ChestWithDistance(ChestAccessor chest, float distance) {
ChestWithDistance(TileEntityChest chest, float distance) {
this.chest = chest;
this.distance = distance;
}
Expand All @@ -36,20 +34,19 @@ public int costToUse(World world, int x, int y, int z, EntityPlayer player) {

GearInfo<GearChestSorter>[] gearInfo = getConnected(world, x, y, z, GearChestSorter.class);

ArrayList<ChestWithDistance> chests = new ArrayList<ChestWithDistance>();
int chests = 0;

// check above each gear for a chest
for (int i = 0; i < gearInfo.length; i++) {
int[] coordinates = gearInfo[i].getCoordinates();
int[] chestCoordinates = {coordinates[0], coordinates[1] + 1, coordinates[2]};
if (Block.blocksList[world.getBlockId(chestCoordinates[0], chestCoordinates[1], chestCoordinates[2])] instanceof BlockChest) {
// chests.add((ChestAccessor)(TileEntityChest)world.getBlockTileEntity(chestCoordinates[0], chestCoordinates[1], chestCoordinates[2]));
chests.add(new ChestWithDistance((ChestAccessor)(TileEntityChest)world.getBlockTileEntity(chestCoordinates[0], chestCoordinates[1], chestCoordinates[2]), gearInfo[i].getDistance()));
chests++;
}
}

// return check count * 2
return chests.size() * 2;
return chests * 2;

} else {
// return 0 if no chest above
Expand All @@ -67,111 +64,91 @@ public int onGearUsed(World world, int x, int y, int z, EntityPlayer player) {

GearInfo<GearChestSorter>[] gearInfo = getConnected(world, x, y, z, GearChestSorter.class);

ArrayList<ChestWithDistance> chests = new ArrayList<ChestWithDistance>();
ChestWithDistance[] chests = new ChestWithDistance[gearInfo.length];

// check above each gear for a chest
for (int i = 0; i < gearInfo.length; i++) {
int[] coordinates = gearInfo[i].getCoordinates();
int[] chestCoordinates = {coordinates[0], coordinates[1] + 1, coordinates[2]};
if (Block.blocksList[world.getBlockId(chestCoordinates[0], chestCoordinates[1], chestCoordinates[2])] instanceof BlockChest) {
// chests.add((ChestAccessor)(TileEntityChest)world.getBlockTileEntity(chestCoordinates[0], chestCoordinates[1], chestCoordinates[2]));
chests.add(new ChestWithDistance((ChestAccessor)(TileEntityChest)world.getBlockTileEntity(chestCoordinates[0], chestCoordinates[1], chestCoordinates[2]), gearInfo[i].getDistance()));
TileEntity tileEntity = world.getBlockTileEntity(chestCoordinates[0], chestCoordinates[1], chestCoordinates[2]);
if (tileEntity instanceof TileEntityChest) {
chests[i] = new ChestWithDistance((TileEntityChest)tileEntity, gearInfo[i].getDistance());
}
}

// sort chests by size and distance largest first, then closest first
List<ChestWithDistance> sortedChestWithDistance = chests.stream()
.sorted(Comparator
.<ChestWithDistance>comparingInt(chestWithDistance -> chestWithDistance.chest.getChestContents().length)
.reversed()
.thenComparing(chestWithDistance -> chestWithDistance.distance))
.collect(Collectors.toList());

ChestAccessor[] chestAccessors = sortedChestWithDistance.stream()
.map(chestWithDistance -> chestWithDistance.chest)
.toArray(ChestAccessor[]::new);

// to get the maximum possible length, we need to add up the lengths of all the chests - this might account for other mods that increase chest size
int fullLength = 0;
for (int i = 0; i < chestAccessors.length; i++) {
fullLength += chestAccessors[i].getChestContents().length;
}
// filter out null chests
chests = Arrays.stream(chests).filter(chest -> chest != null).toArray(ChestWithDistance[]::new);

// sort chests by distance
Arrays.sort(chests, new Comparator<ChestWithDistance>() {
@Override
public int compare(ChestWithDistance a, ChestWithDistance b) {
return Float.compare(a.distance, b.distance);
}
});

ItemStack[] allItems = new ItemStack[fullLength];
// get all items from all chests
ArrayList<ItemStack> allItems = new ArrayList<ItemStack>();

// copy all items from all chests into allItems
int index = 0;
for (int i = 0; i < chestAccessors.length; i++) {
ItemStack[] chestContents = chestAccessors[i].getChestContents();
// go through all chests and add all items to allItems, then clear the chest
for (int i = 0; i < chests.length; i++) {
ItemStack[] chestContents = ((ChestAccessor)chests[i].chest).getChestContents();
for (int j = 0; j < chestContents.length; j++) {
allItems[index] = chestContents[j];
index++;
if (chestContents[j] != null) {
allItems.add(chestContents[j]);
chestContents[j] = null;
}
}
}

// sort allItems by itemID
ItemStack[] sortedItems = Arrays.stream(allItems)
.filter(itemStack -> itemStack != null)
.sorted(Comparator.comparingInt(itemStack -> itemStack.itemID))
.toArray(ItemStack[]::new);

// reducedItems tries to merge itemStacks together
ItemStack[] reducedItems = new ItemStack[sortedItems.length];

// loop through sortedItems, if the item is the same as the previous item, add the stackSize to the previous item, otherwise add the item to reducedItems
index = 0;
for (int i = 0; i < sortedItems.length; i++) {
if (i == 0) {
reducedItems[index] = sortedItems[i];
index++;
} else {
if (sortedItems[i].itemID == reducedItems[index - 1].itemID) {
// there is an ItemStack.getMaxStackSize
int previousStackSize = reducedItems[index - 1].stackSize;
int currentStackSize = sortedItems[i].stackSize;
int previousRoomLeft = reducedItems[index - 1].getMaxStackSize() - previousStackSize;
int amountToReduce = Math.min(currentStackSize, previousRoomLeft);

// increase previous and decrease current
reducedItems[index - 1].stackSize += amountToReduce;
sortedItems[i].stackSize -= amountToReduce;

// if current is now empty, delete it
if(sortedItems[i].stackSize < 1) {
sortedItems[i] = null;
} else {
reducedItems[index] = sortedItems[i];
index++;
}

// sort allItems by max stack size, then by name
allItems.sort(new Comparator<ItemStack>() {
@Override
public int compare(ItemStack a, ItemStack b) {
int maxSizeCompare = Integer.compare(a.getMaxStackSize(), b.getMaxStackSize());
if (maxSizeCompare == 0) {
return a.getItemName().compareTo(b.getItemName());
} else {
reducedItems[index] = sortedItems[i];
index++;
return maxSizeCompare;
}
}
});

// merge like itemstacks
// itemstacks have getMaxStackSize() and getItem
// if itemstack.getItem() == item.getItem(), consider merging,
int index = 0;
// until we've checked them all
while(index < allItems.size()) {
ItemStack currentItem = allItems.get(index);
// if the next item is the same item and the current item is not full, keep going
while(index + 1 < allItems.size() && currentItem.getItem() == allItems.get(index + 1).getItem() && currentItem.stackSize < currentItem.getMaxStackSize()) {
ItemStack nextItem = allItems.get(index + 1);
// if the next item can fit in the current item, merge it
if (currentItem.stackSize + nextItem.stackSize <= currentItem.getMaxStackSize()) {
currentItem.stackSize += nextItem.stackSize;
allItems.remove(index + 1);
} else {
// otherwise, fill the current item and move on
nextItem.stackSize -= currentItem.getMaxStackSize() - currentItem.stackSize;
currentItem.stackSize = currentItem.getMaxStackSize();
break;
}
}
index++;
}

// sort by getMaxSize and then getItemName
reducedItems = Arrays.stream(reducedItems)
.filter(itemStack -> itemStack != null)
.sorted(Comparator.comparingInt(ItemStack::getMaxStackSize).thenComparing(ItemStack::getItemName))
.toArray(ItemStack[]::new);

// put all items back into chests
index = 0;
for (int i = 0; i < chestAccessors.length; i++) {
ItemStack[] chestContents = chestAccessors[i].getChestContents();
ItemStack[] newChestContents = new ItemStack[chestContents.length];
// go through all chests and add items from allItems to the chest
for (int i = 0; i < chests.length; i++) {
ItemStack[] chestContents = ((ChestAccessor)chests[i].chest).getChestContents();
for (int j = 0; j < chestContents.length; j++) {
if(index < reducedItems.length) {
newChestContents[j] = reducedItems[index];
if (chestContents[j] == null && allItems.size() > 0) {
chestContents[j] = allItems.remove(0);
}
index++;
}
chestAccessors[i].setChestContents(newChestContents);
}
return chestAccessors.length * 2;

return chests.length * 2;
}

return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,6 @@ public boolean blockActivated(World world, int x, int y, int z, EntityPlayer pla

// spawn particles
int value = gearUsable.getGear().onGearUsed(world, coords[0], coords[1], coords[2], player);
// log value
System.out.println("Value: " + value);

showWorking(world, x, y, z, player);
// 1 in 10 chance of breaking a bone for every value
Expand Down

0 comments on commit 62d3e75

Please sign in to comment.