Fixed issue with server not properly handling item rotations when trying to fit an item into a container

Added small optimisations to skip full rows when looking for a free slot to put item in
Added small optimisation to skip looking for a free slot when entire container is full
Fixed error messages not properly being passed back up chain
This commit is contained in:
Dev 2024-02-09 17:13:19 +00:00
parent 8b6de1a7ea
commit 1cfc7f2a16
2 changed files with 28 additions and 30 deletions

View File

@ -34,24 +34,31 @@ export class ContainerHelper
const limitY = containerY - minVolume; const limitY = containerY - minVolume;
const limitX = containerX - minVolume; const limitX = containerX - minVolume;
// Every slot taken up, exit // Every x+y slot taken up in container, exit
if (container2D.every((x) => x.every((y) => y === 1))) if (container2D.every((x) => x.every((y) => y === 1)))
{ {
return new FindSlotResult(false); return new FindSlotResult(false);
} }
// Down
for (let y = 0; y < limitY; y++) for (let y = 0; y < limitY; y++)
{ {
// Across
if (container2D[y].every((x) => x === 1))
{
// Every item in row is full, skip row
continue;
}
for (let x = 0; x < limitX; x++) for (let x = 0; x < limitX; x++)
{ {
let foundSlot = this.locateSlot(container2D, containerX, containerY, x, y, itemWidth, itemHeight); let foundSlot = this.locateSlot(container2D, containerX, containerY, x, y, itemWidth, itemHeight);
/** // Failed to find slot, rotate item and try again
* Failed to find slot, rotate item and try again
*/
if (!foundSlot && itemWidth * itemHeight > 1) if (!foundSlot && itemWidth * itemHeight > 1)
{ // bigger than 1x1 {
foundSlot = this.locateSlot(container2D, containerX, containerY, x, y, itemHeight, itemWidth); // Bigger than 1x1
foundSlot = this.locateSlot(container2D, containerX, containerY, x, y, itemHeight, itemWidth); // Height/Width swapped
if (foundSlot) if (foundSlot)
{ {
// Found a slot for it when rotated // Found a slot for it when rotated
@ -104,7 +111,7 @@ export class ContainerHelper
break; break;
} }
// Does item fit x-ways // Does item fit x-ways across
for (let itemX = 0; itemX < itemW; itemX++) for (let itemX = 0; itemX < itemW; itemX++)
{ {
if (foundSlot && x + itemW - 1 > containerX - 1) if (foundSlot && x + itemW - 1 > containerX - 1)
@ -131,7 +138,7 @@ export class ContainerHelper
/** /**
* Find a free slot for an item to be placed at * Find a free slot for an item to be placed at
* @param container2D Container to palce item in * @param container2D Container to place item in
* @param x Container x size * @param x Container x size
* @param y Container y size * @param y Container y size
* @param itemW Items width * @param itemW Items width
@ -147,6 +154,7 @@ export class ContainerHelper
rotate: boolean, rotate: boolean,
): void ): void
{ {
// Swap height/width if we want to fit it in rotated
const itemWidth = rotate ? itemH : itemW; const itemWidth = rotate ? itemH : itemW;
const itemHeight = rotate ? itemW : itemH; const itemHeight = rotate ? itemW : itemH;
@ -156,11 +164,12 @@ export class ContainerHelper
{ {
if (container2D[tmpY][tmpX] === 0) if (container2D[tmpY][tmpX] === 0)
{ {
// Flag slot as used
container2D[tmpY][tmpX] = 1; container2D[tmpY][tmpX] = 1;
} }
else else
{ {
throw new Error(`Slot at (${x}, ${y}) is already filled`); throw new Error(`Slot at (${x}, ${y}) is already filled. Cannot fit a ${itemW} by ${itemH}`);
} }
} }
} }

View File

@ -236,7 +236,7 @@ export class InventoryHelper
{ {
const pmcData = this.profileHelper.getPmcProfile(sessionId); const pmcData = this.profileHelper.getPmcProfile(sessionId);
const stashFS2D = this.getStashSlotMap(pmcData, sessionId); const stashFS2D = this.jsonUtil.clone(this.getStashSlotMap(pmcData, sessionId));
for (const itemWithChildren of itemsWithChildren) for (const itemWithChildren of itemsWithChildren)
{ {
if (this.canPlaceItemInInventory(stashFS2D, itemWithChildren)) if (this.canPlaceItemInInventory(stashFS2D, itemWithChildren))
@ -258,25 +258,20 @@ export class InventoryHelper
const findSlotResult = this.containerHelper.findSlotForItem(stashFS2D, itemSize[0], itemSize[1]); const findSlotResult = this.containerHelper.findSlotForItem(stashFS2D, itemSize[0], itemSize[1]);
if (findSlotResult.success) if (findSlotResult.success)
{ {
/* Fill in the StashFS_2D with an imaginary item, to simulate it already being added
* so the next item to search for a free slot won't find the same one */
const itemSizeX = findSlotResult.rotation ? itemSize[1] : itemSize[0];
const itemSizeY = findSlotResult.rotation ? itemSize[0] : itemSize[1];
try try
{ {
this.containerHelper.fillContainerMapWithItem( this.containerHelper.fillContainerMapWithItem(
stashFS2D, stashFS2D,
findSlotResult.x, findSlotResult.x,
findSlotResult.y, findSlotResult.y,
itemSizeX, itemSize[0],
itemSizeY, itemSize[1],
findSlotResult.rotation, findSlotResult.rotation,
); );
} }
catch (err) catch (err)
{ {
const errorText = (typeof err === "string") ? ` -> ${err}` : ""; const errorText = (typeof err === "string") ? ` -> ${err}` : err.message;
this.logger.error(`Unable to fit item into inventory: ${errorText}`); this.logger.error(`Unable to fit item into inventory: ${errorText}`);
return false; return false;
@ -315,25 +310,20 @@ export class InventoryHelper
const findSlotResult = this.containerHelper.findSlotForItem(stashFS2D, itemSize[0], itemSize[1]); const findSlotResult = this.containerHelper.findSlotForItem(stashFS2D, itemSize[0], itemSize[1]);
if (findSlotResult.success) if (findSlotResult.success)
{ {
/* Fill in the StashFS_2D with an imaginary item, to simulate it already being added
* so the next item to search for a free slot won't find the same one */
const itemSizeX = findSlotResult.rotation ? itemSize[1] : itemSize[0];
const itemSizeY = findSlotResult.rotation ? itemSize[0] : itemSize[1];
try try
{ {
this.containerHelper.fillContainerMapWithItem( this.containerHelper.fillContainerMapWithItem(
stashFS2D, stashFS2D,
findSlotResult.x, findSlotResult.x,
findSlotResult.y, findSlotResult.y,
itemSizeX, itemSize[0],
itemSizeY, itemSize[1],
findSlotResult.rotation, findSlotResult.rotation,
); );
} }
catch (err) catch (err)
{ {
const errorText = (typeof err === "string") ? ` -> ${err}` : ""; const errorText = (typeof err === "string") ? ` -> ${err}` : err.message;
this.logger.error(this.localisationService.getText("inventory-fill_container_failed", errorText)); this.logger.error(this.localisationService.getText("inventory-fill_container_failed", errorText));
this.httpResponse.appendErrorToOutput( this.httpResponse.appendErrorToOutput(
@ -365,16 +355,15 @@ export class InventoryHelper
itemSize[0], itemSize[0],
itemSize[1], itemSize[1],
); );
const itemSizeX = findSortingSlotResult.rotation ? itemSize[1] : itemSize[0];
const itemSizeY = findSortingSlotResult.rotation ? itemSize[0] : itemSize[1];
try try
{ {
this.containerHelper.fillContainerMapWithItem( this.containerHelper.fillContainerMapWithItem(
sortingTableFS2D, sortingTableFS2D,
findSortingSlotResult.x, findSortingSlotResult.x,
findSortingSlotResult.y, findSortingSlotResult.y,
itemSizeX, itemSize[0],
itemSizeY, itemSize[1],
findSortingSlotResult.rotation, findSortingSlotResult.rotation,
); );
} }