mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-26 17:43:48 +01:00
Fix for invalid materials in warehouse (#660)
This commit is contained in:
parent
26cdc502bf
commit
312e3eb71f
@ -249,14 +249,26 @@ export function SetSmartSupplyOption(warehouse: Warehouse, material: Material, u
|
|||||||
warehouse.smartSupplyOptions[material.name] = useOption;
|
warehouse.smartSupplyOptions[material.name] = useOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BuyMaterial(material: Material, amt: number): void {
|
export function BuyMaterial(division: Division, material: Material, amt: number): void {
|
||||||
|
if (!isRelevantMaterial(material.name, division)) {
|
||||||
|
throw new Error(`${material.name} is not a relevant material for industry ${division.type}`);
|
||||||
|
}
|
||||||
if (isNaN(amt) || amt < 0) {
|
if (isNaN(amt) || amt < 0) {
|
||||||
throw new Error(`Invalid amount '${amt}' to buy material '${material.name}'`);
|
throw new Error(`Invalid amount '${amt}' to buy material '${material.name}'`);
|
||||||
}
|
}
|
||||||
material.buyAmount = amt;
|
material.buyAmount = amt;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BulkPurchase(corp: Corporation, warehouse: Warehouse, material: Material, amt: number): void {
|
export function BulkPurchase(
|
||||||
|
corp: Corporation,
|
||||||
|
division: Division,
|
||||||
|
warehouse: Warehouse,
|
||||||
|
material: Material,
|
||||||
|
amt: number,
|
||||||
|
): void {
|
||||||
|
if (!isRelevantMaterial(material.name, division)) {
|
||||||
|
throw new Error(`${material.name} is not a relevant material for industry ${division.type}`);
|
||||||
|
}
|
||||||
const matSize = MaterialInfo[material.name].size;
|
const matSize = MaterialInfo[material.name].size;
|
||||||
const maxAmount = (warehouse.size - warehouse.sizeUsed) / matSize;
|
const maxAmount = (warehouse.size - warehouse.sizeUsed) / matSize;
|
||||||
if (isNaN(amt) || amt < 0) {
|
if (isNaN(amt) || amt < 0) {
|
||||||
|
@ -16,27 +16,30 @@ import MenuItem from "@mui/material/MenuItem";
|
|||||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||||
import { useRerender } from "../../../ui/React/hooks";
|
import { useRerender } from "../../../ui/React/hooks";
|
||||||
import { getRecordKeys } from "../../../Types/Record";
|
import { getRecordKeys } from "../../../Types/Record";
|
||||||
|
import { ButtonWithTooltip } from "../../../ui/Components/ButtonWithTooltip";
|
||||||
|
|
||||||
interface IProps {
|
interface ExportModalProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
mat: Material;
|
mat: Material;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a popup that lets the player manage exports
|
// Create a popup that lets the player manage exports
|
||||||
export function ExportModal(props: IProps): React.ReactElement {
|
export function ExportModal(props: ExportModalProps): React.ReactElement {
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
|
const [exportAmount, setExportAmount] = useState("");
|
||||||
|
const rerender = useRerender();
|
||||||
|
|
||||||
const possibleDivisions = [...corp.divisions.values()].filter((division: Division) => {
|
const possibleDivisions = [...corp.divisions.values()].filter((division: Division) => {
|
||||||
return isRelevantMaterial(props.mat.name, division);
|
return isRelevantMaterial(props.mat.name, division);
|
||||||
});
|
});
|
||||||
if (possibleDivisions.length === 0) throw new Error("Export popup created with no divisions.");
|
// This weird assignment is used because ts thinks possibleDivisions[0] is always a division
|
||||||
const defaultDivision = possibleDivisions[0];
|
const defaultDivision = possibleDivisions.length ? possibleDivisions[0] : null;
|
||||||
if (Object.keys(defaultDivision.warehouses).length === 0)
|
const [targetDivision, setTargetDivision] = useState<Division | null>(defaultDivision);
|
||||||
throw new Error("Export popup created in a division with no warehouses.");
|
|
||||||
const [targetDivision, setTargetDivision] = useState(defaultDivision);
|
const possibleCities = targetDivision ? getRecordKeys(targetDivision.warehouses) : [];
|
||||||
const [targetCity, setTargetCity] = useState(CityName.Sector12);
|
const defaultCity = possibleCities.length ? possibleCities[0] : null;
|
||||||
const [exportAmount, setExportAmount] = useState("");
|
const [targetCity, setTargetCity] = useState(defaultCity);
|
||||||
const rerender = useRerender();
|
|
||||||
|
|
||||||
function onCityChange(event: SelectChangeEvent<CityName>): void {
|
function onCityChange(event: SelectChangeEvent<CityName>): void {
|
||||||
setTargetCity(event.target.value as CityName);
|
setTargetCity(event.target.value as CityName);
|
||||||
@ -54,6 +57,7 @@ export function ExportModal(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
function exportMaterial(): void {
|
function exportMaterial(): void {
|
||||||
try {
|
try {
|
||||||
|
if (!targetDivision || !targetCity) return;
|
||||||
ExportMaterial(targetDivision, targetCity, props.mat, exportAmount);
|
ExportMaterial(targetDivision, targetCity, props.mat, exportAmount);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
dialogBoxCreate(err + "");
|
dialogBoxCreate(err + "");
|
||||||
@ -75,9 +79,8 @@ export function ExportModal(props: IProps): React.ReactElement {
|
|||||||
rerender();
|
rerender();
|
||||||
}
|
}
|
||||||
|
|
||||||
const possibleCities = getRecordKeys(targetDivision.warehouses);
|
if (targetCity && !possibleCities.includes(targetCity as CityName)) {
|
||||||
if (possibleCities.length > 0 && !possibleCities.includes(targetCity)) {
|
setTargetCity(possibleCities.length ? possibleCities[0] : null);
|
||||||
setTargetCity(possibleCities[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -104,16 +107,14 @@ export function ExportModal(props: IProps): React.ReactElement {
|
|||||||
<br />
|
<br />
|
||||||
For example: setting the amount "(EINV-20)/10" would try to export all except 20 of the material.
|
For example: setting the amount "(EINV-20)/10" would try to export all except 20 of the material.
|
||||||
</Typography>
|
</Typography>
|
||||||
<Select onChange={onTargetDivisionChange} value={targetDivision.name}>
|
<Select onChange={onTargetDivisionChange} value={targetDivision?.name ?? ""}>
|
||||||
{[...corp.divisions.values()]
|
{possibleDivisions.map((division) => (
|
||||||
.filter((division) => isRelevantMaterial(props.mat.name, division))
|
|
||||||
.map((division) => (
|
|
||||||
<MenuItem key={division.name} value={division.name}>
|
<MenuItem key={division.name} value={division.name}>
|
||||||
{division.name}
|
{division.name}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
<Select onChange={onCityChange} value={targetCity}>
|
<Select onChange={onCityChange} value={targetCity ?? ""}>
|
||||||
{possibleCities.map((cityName) => (
|
{possibleCities.map((cityName) => (
|
||||||
<MenuItem key={cityName} value={cityName}>
|
<MenuItem key={cityName} value={cityName}>
|
||||||
{cityName}
|
{cityName}
|
||||||
@ -121,7 +122,12 @@ export function ExportModal(props: IProps): React.ReactElement {
|
|||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
<TextField placeholder="Export amount / s" onChange={onAmtChange} value={exportAmount} />
|
<TextField placeholder="Export amount / s" onChange={onAmtChange} value={exportAmount} />
|
||||||
<Button onClick={exportMaterial}>Export</Button>
|
<ButtonWithTooltip
|
||||||
|
disabledTooltip={!targetDivision ? "No target division selected" : !targetCity ? "No target city selected" : ""}
|
||||||
|
onClick={exportMaterial}
|
||||||
|
>
|
||||||
|
Export
|
||||||
|
</ButtonWithTooltip>
|
||||||
<Typography>
|
<Typography>
|
||||||
Below is a list of all current exports of this material from this warehouse. Clicking on one of the exports
|
Below is a list of all current exports of this material from this warehouse. Clicking on one of the exports
|
||||||
below will REMOVE that export.
|
below will REMOVE that export.
|
||||||
|
@ -6,7 +6,7 @@ import { Material } from "../../Material";
|
|||||||
import { formatMatPurchaseAmount, formatMoney } from "../../../ui/formatNumber";
|
import { formatMatPurchaseAmount, formatMoney } from "../../../ui/formatNumber";
|
||||||
import { BulkPurchase, BuyMaterial } from "../../Actions";
|
import { BulkPurchase, BuyMaterial } from "../../Actions";
|
||||||
import { Modal } from "../../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { useCorporation } from "../Context";
|
import { useCorporation, useDivision } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
@ -26,6 +26,7 @@ interface IBPProps {
|
|||||||
|
|
||||||
function BulkPurchaseSection(props: IBPProps): React.ReactElement {
|
function BulkPurchaseSection(props: IBPProps): React.ReactElement {
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
|
const division = useDivision();
|
||||||
const [buyAmt, setBuyAmt] = useState("");
|
const [buyAmt, setBuyAmt] = useState("");
|
||||||
const [disabled, setDisabled] = useState(false);
|
const [disabled, setDisabled] = useState(false);
|
||||||
|
|
||||||
@ -64,7 +65,7 @@ function BulkPurchaseSection(props: IBPProps): React.ReactElement {
|
|||||||
|
|
||||||
function bulkPurchase(): void {
|
function bulkPurchase(): void {
|
||||||
try {
|
try {
|
||||||
BulkPurchase(corp, props.warehouse, props.mat, parseFloat(buyAmt));
|
BulkPurchase(corp, division, props.warehouse, props.mat, parseFloat(buyAmt));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
dialogBoxCreate(err + "");
|
dialogBoxCreate(err + "");
|
||||||
}
|
}
|
||||||
@ -110,12 +111,13 @@ interface IProps {
|
|||||||
|
|
||||||
// Create a popup that lets the player purchase a Material
|
// Create a popup that lets the player purchase a Material
|
||||||
export function PurchaseMaterialModal(props: IProps): React.ReactElement {
|
export function PurchaseMaterialModal(props: IProps): React.ReactElement {
|
||||||
|
const division = useDivision();
|
||||||
const [buyAmt, setBuyAmt] = useState(props.mat.buyAmount ? props.mat.buyAmount : 0);
|
const [buyAmt, setBuyAmt] = useState(props.mat.buyAmount ? props.mat.buyAmount : 0);
|
||||||
|
|
||||||
function purchaseMaterial(): void {
|
function purchaseMaterial(): void {
|
||||||
if (buyAmt === null) return;
|
if (buyAmt === null) return;
|
||||||
try {
|
try {
|
||||||
BuyMaterial(props.mat, buyAmt);
|
BuyMaterial(division, props.mat, buyAmt);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
dialogBoxCreate(err + "");
|
dialogBoxCreate(err + "");
|
||||||
}
|
}
|
||||||
|
@ -416,24 +416,28 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
|||||||
buyMaterial: (ctx) => (_divisionName, _cityName, _materialName, _amt) => {
|
buyMaterial: (ctx) => (_divisionName, _cityName, _materialName, _amt) => {
|
||||||
checkAccess(ctx, CorpUnlockName.WarehouseAPI);
|
checkAccess(ctx, CorpUnlockName.WarehouseAPI);
|
||||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||||
|
const division = getCorporation().divisions.get(divisionName);
|
||||||
|
if (!division) throw helpers.makeRuntimeErrorMsg(ctx, `No division with provided name ${divisionName}`);
|
||||||
const cityName = getEnumHelper("CityName").nsGetMember(ctx, _cityName);
|
const cityName = getEnumHelper("CityName").nsGetMember(ctx, _cityName);
|
||||||
const materialName = getEnumHelper("CorpMaterialName").nsGetMember(ctx, _materialName, "materialName");
|
const materialName = getEnumHelper("CorpMaterialName").nsGetMember(ctx, _materialName, "materialName");
|
||||||
const amt = helpers.number(ctx, "amt", _amt);
|
const amt = helpers.number(ctx, "amt", _amt);
|
||||||
if (amt < 0 || !Number.isFinite(amt))
|
if (amt < 0 || !Number.isFinite(amt))
|
||||||
throw new Error("Invalid value for amount field! Must be numeric and greater than 0");
|
throw new Error("Invalid value for amount field! Must be numeric and greater than 0");
|
||||||
const material = getMaterial(divisionName, cityName, materialName);
|
const material = getMaterial(divisionName, cityName, materialName);
|
||||||
BuyMaterial(material, amt);
|
BuyMaterial(division, material, amt);
|
||||||
},
|
},
|
||||||
bulkPurchase: (ctx) => (_divisionName, _cityName, _materialName, _amt) => {
|
bulkPurchase: (ctx) => (_divisionName, _cityName, _materialName, _amt) => {
|
||||||
checkAccess(ctx, CorpUnlockName.WarehouseAPI);
|
checkAccess(ctx, CorpUnlockName.WarehouseAPI);
|
||||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||||
|
const division = getCorporation().divisions.get(divisionName);
|
||||||
|
if (!division) throw helpers.makeRuntimeErrorMsg(ctx, `No division with provided name ${divisionName}`);
|
||||||
const corporation = getCorporation();
|
const corporation = getCorporation();
|
||||||
const cityName = getEnumHelper("CityName").nsGetMember(ctx, _cityName);
|
const cityName = getEnumHelper("CityName").nsGetMember(ctx, _cityName);
|
||||||
const materialName = getEnumHelper("CorpMaterialName").nsGetMember(ctx, _materialName, "materialName");
|
const materialName = getEnumHelper("CorpMaterialName").nsGetMember(ctx, _materialName, "materialName");
|
||||||
const amt = helpers.number(ctx, "amt", _amt);
|
const amt = helpers.number(ctx, "amt", _amt);
|
||||||
const warehouse = getWarehouse(divisionName, cityName);
|
const warehouse = getWarehouse(divisionName, cityName);
|
||||||
const material = getMaterial(divisionName, cityName, materialName);
|
const material = getMaterial(divisionName, cityName, materialName);
|
||||||
BulkPurchase(corporation, warehouse, material, amt);
|
BulkPurchase(corporation, division, warehouse, material, amt);
|
||||||
},
|
},
|
||||||
makeProduct:
|
makeProduct:
|
||||||
(ctx) =>
|
(ctx) =>
|
||||||
|
Loading…
Reference in New Issue
Block a user