1
0
Fork 0

style(lib): format shared libraries and remove unused imports

This commit is contained in:
Jason Fraley 2026-08-16 23:27:51 -04:00
parent 5058d9ce6c
commit 6685fe68cd
11 changed files with 94 additions and 66 deletions

View file

@ -57,9 +57,10 @@ export async function setMissionAttendance(
const mission = (await payload const mission = (await payload
.findByID({ collection: "missions", id: missionId, depth: 0, overrideAccess: true }) .findByID({ collection: "missions", id: missionId, depth: 0, overrideAccess: true })
.catch(() => null)) as unknown as .catch(() => null)) as unknown as {
| { name?: string; classification: { startDateTime: string } } name?: string;
| null; classification: { startDateTime: string };
} | null;
if (!mission) throw new Error("Mission not found."); if (!mission) throw new Error("Mission not found.");
if (isMissionPast(mission.classification.startDateTime)) { if (isMissionPast(mission.classification.startDateTime)) {

View file

@ -1,4 +1,3 @@
import type { Payload } from "payload";
import type { BankAccount, BankTransaction } from "@/payload-types"; import type { BankAccount, BankTransaction } from "@/payload-types";
export type BankAccountType = "treasury" | "faction" | "personal"; export type BankAccountType = "treasury" | "faction" | "personal";
@ -93,7 +92,10 @@ export async function createAccount(
})) as unknown as BankAccount; })) as unknown as BankAccount;
} }
export async function ensurePersonalAccount(payload: PayloadType, userId: number): Promise<BankAccount> { export async function ensurePersonalAccount(
payload: PayloadType,
userId: number,
): Promise<BankAccount> {
const existing = (await payload.find({ const existing = (await payload.find({
collection: "bank-accounts", collection: "bank-accounts",
where: { where: {
@ -105,12 +107,14 @@ export async function ensurePersonalAccount(payload: PayloadType, userId: number
})) as unknown as { docs: BankAccount[] }; })) as unknown as { docs: BankAccount[] };
if (existing.docs.length > 0) return existing.docs[0]; if (existing.docs.length > 0) return existing.docs[0];
const user = (await payload.findByID({ const user = (await payload
.findByID({
collection: "users", collection: "users",
id: userId, id: userId,
depth: 0, depth: 0,
overrideAccess: true, overrideAccess: true,
}).catch(() => null)) as unknown as { username?: string; displayName?: string } | null; })
.catch(() => null)) as unknown as { username?: string; displayName?: string } | null;
const label = user?.displayName || user?.username || `User ${userId}`; const label = user?.displayName || user?.username || `User ${userId}`;
return createAccount(payload, { return createAccount(payload, {

View file

@ -1,4 +1,3 @@
import type { Payload } from "payload";
import type { Asset, LockerStorage } from "@/payload-types"; import type { Asset, LockerStorage } from "@/payload-types";
import type { GridDimensions } from "@/lib/logistics"; import type { GridDimensions } from "@/lib/logistics";

View file

@ -1,10 +1,10 @@
import type { Asset, Loadout } from "@/payload-types"; import type { Asset, Loadout } from "@/payload-types";
import { import {
WARDROBE_SLOT_LAYOUT,
getAssetTypeLabel, getAssetTypeLabel,
getLoadoutSlot, getLoadoutSlot,
type LoadoutSlots, type LoadoutSlots,
type LockerGridItem, type LockerGridItem,
WARDROBE_SLOT_LAYOUT,
} from "@/lib/locker"; } from "@/lib/locker";
export type LockerSearchLocationKind = "locker" | "attached" | "skin" | "loadout"; export type LockerSearchLocationKind = "locker" | "attached" | "skin" | "loadout";
@ -77,11 +77,14 @@ export function buildAssetStats(asset: Asset): LockerSearchStat[] {
if (mag?.ammoType) stats.push({ label: "Ammo", value: mag.ammoType }); if (mag?.ammoType) stats.push({ label: "Ammo", value: mag.ammoType });
const container = asset["Container Configuration"]; const container = asset["Container Configuration"];
if (container?.capacityKg != null) stats.push({ label: "Capacity", value: `${container.capacityKg}kg` }); if (container?.capacityKg != null)
if (container?.weightKg != null) stats.push({ label: "Weight", value: `${container.weightKg}kg` }); stats.push({ label: "Capacity", value: `${container.capacityKg}kg` });
if (container?.weightKg != null)
stats.push({ label: "Weight", value: `${container.weightKg}kg` });
const nvg = asset["Nightvision Configuration"]; const nvg = asset["Nightvision Configuration"];
if (nvg?.nvgGeneration) stats.push({ label: "Gen", value: NVG_GEN_LABELS[nvg.nvgGeneration] ?? nvg.nvgGeneration }); if (nvg?.nvgGeneration)
stats.push({ label: "Gen", value: NVG_GEN_LABELS[nvg.nvgGeneration] ?? nvg.nvgGeneration });
if (nvg?.nvgHasThermals) stats.push({ label: "Thermals", value: "Yes" }); if (nvg?.nvgHasThermals) stats.push({ label: "Thermals", value: "Yes" });
const skin = asset["Skin Configuration"]; const skin = asset["Skin Configuration"];
@ -93,7 +96,8 @@ export function buildAssetStats(asset: Asset): LockerSearchStat[] {
} }
const market = asset.marketTrading; const market = asset.marketTrading;
if (market?.Rarity) stats.push({ label: "Rarity", value: RARITY_LABELS[market.Rarity] ?? market.Rarity }); if (market?.Rarity)
stats.push({ label: "Rarity", value: RARITY_LABELS[market.Rarity] ?? market.Rarity });
const dims = asset.storageDimensions; const dims = asset.storageDimensions;
if (dims?.gridWidth != null && dims?.gridHeight != null) { if (dims?.gridWidth != null && dims?.gridHeight != null) {

View file

@ -70,7 +70,10 @@ export function buildChatBubbles(
const fallbackRng = negotiation ? seededRng(negotiation.id) : Math.random; const fallbackRng = negotiation ? seededRng(negotiation.id) : Math.random;
if (negotiation?.status === "accepted" && !hasDialogue) { if (negotiation?.status === "accepted" && !hasDialogue) {
bubbles.push({ from: "seller", text: npcDialogue("accept", undefined, undefined, fallbackRng) }); bubbles.push({
from: "seller",
text: npcDialogue("accept", undefined, undefined, fallbackRng),
});
} else if (negotiation?.status === "closed" && !hasDialogue) { } else if (negotiation?.status === "closed" && !hasDialogue) {
bubbles.push({ bubbles.push({
from: "seller", from: "seller",

View file

@ -1,4 +1,3 @@
import type { Payload } from "payload";
import type { Asset, LockerStorage, MarketListing, User } from "@/payload-types"; import type { Asset, LockerStorage, MarketListing, User } from "@/payload-types";
import { import {
ensureLockerStorage, ensureLockerStorage,
@ -10,11 +9,7 @@ import {
resolveAssetId, resolveAssetId,
toLockerGridItems, toLockerGridItems,
} from "@/lib/locker"; } from "@/lib/locker";
import { import { applyTransaction, ensurePersonalAccount, getMainCurrencyId } from "@/lib/banking";
applyTransaction,
ensurePersonalAccount,
getMainCurrencyId,
} from "@/lib/banking";
type PayloadType = Awaited<ReturnType<typeof import("payload").getPayload>>; type PayloadType = Awaited<ReturnType<typeof import("payload").getPayload>>;
@ -65,14 +60,18 @@ export interface NegotiationRange {
} }
/** Resolve a listing's negotiation range. Non-negotiable listings have min === desired. */ /** Resolve a listing's negotiation range. Non-negotiable listings have min === desired. */
export function negotiationRange(listing: Pick<MarketListing, "price" | "desiredPrice" | "minPrice">): NegotiationRange { export function negotiationRange(
listing: Pick<MarketListing, "price" | "desiredPrice" | "minPrice">,
): NegotiationRange {
const desired = listing.desiredPrice ?? listing.price ?? 0; const desired = listing.desiredPrice ?? listing.price ?? 0;
const min = listing.minPrice ?? desired; const min = listing.minPrice ?? desired;
return { min, desired }; return { min, desired };
} }
/** A listing is negotiable when the seller has set a floor below the asking price. */ /** A listing is negotiable when the seller has set a floor below the asking price. */
export function isNegotiable(listing: Pick<MarketListing, "price" | "desiredPrice" | "minPrice">): boolean { export function isNegotiable(
listing: Pick<MarketListing, "price" | "desiredPrice" | "minPrice">,
): boolean {
const { min, desired } = negotiationRange(listing); const { min, desired } = negotiationRange(listing);
return min < desired; return min < desired;
} }
@ -179,7 +178,13 @@ export async function creditLockerQuantity(
while (remaining > 0) { while (remaining > 0) {
const stackAmount = Math.min(remaining, maxStack === Infinity ? remaining : maxStack); const stackAmount = Math.min(remaining, maxStack === Infinity ? remaining : maxStack);
const spot = findLockerEmptySpot(gridItems, footprint.width, footprint.height, grid.width, grid.height); const spot = findLockerEmptySpot(
gridItems,
footprint.width,
footprint.height,
grid.width,
grid.height,
);
if (!spot) { if (!spot) {
throw new Error( throw new Error(
`No space in buyer's locker for ${asset.name}. Needs ${footprint.width}×${footprint.height} free cells.`, `No space in buyer's locker for ${asset.name}. Needs ${footprint.width}×${footprint.height} free cells.`,
@ -266,7 +271,9 @@ export async function buyListing(
} }
const sellerId = const sellerId =
typeof listing.seller === "object" && listing.seller ? listing.seller.id : (listing.seller as number | null); typeof listing.seller === "object" && listing.seller
? listing.seller.id
: (listing.seller as number | null);
if (sellerId != null && sellerId === buyer.id) { if (sellerId != null && sellerId === buyer.id) {
throw new Error("You cannot buy your own listing."); throw new Error("You cannot buy your own listing.");
} }
@ -343,10 +350,17 @@ export async function expireListing(
listing: MarketListing, listing: MarketListing,
): Promise<MarketListing> { ): Promise<MarketListing> {
const sellerId = const sellerId =
typeof listing.seller === "object" && listing.seller ? listing.seller.id : (listing.seller as number | null); typeof listing.seller === "object" && listing.seller
? listing.seller.id
: (listing.seller as number | null);
if (sellerId != null && !listing.isAutoGenerated) { if (sellerId != null && !listing.isAutoGenerated) {
await creditLockerQuantity(payload, sellerId, resolveAssetId(listing.asset) as number, listing.quantity); await creditLockerQuantity(
payload,
sellerId,
resolveAssetId(listing.asset) as number,
listing.quantity,
);
} }
return (await payload.update({ return (await payload.update({

View file

@ -98,7 +98,8 @@ export function npcResponseToOffer(
amount > lastBuyerOffer && amount > lastBuyerOffer &&
amount - lastBuyerOffer < desired * NPC_PATIENCE.stallRatio; amount - lastBuyerOffer < desired * NPC_PATIENCE.stallRatio;
if (amount >= stance) return { action: "accept", amount: Math.min(amount, desired), reason: good(amount) }; if (amount >= stance)
return { action: "accept", amount: Math.min(amount, desired), reason: good(amount) };
if (amount >= stance - margin) { if (amount >= stance - margin) {
if (rng() < NPC_ACCEPT.chance) { if (rng() < NPC_ACCEPT.chance) {
return { action: "accept", amount: Math.min(amount, desired), reason: good(amount) }; return { action: "accept", amount: Math.min(amount, desired), reason: good(amount) };
@ -136,7 +137,11 @@ function advancePatience(
previous: number | null, previous: number | null,
): number { ): number {
let delta: number; let delta: number;
if (previous != null && amount > previous && amount - previous < desired * NPC_PATIENCE.stallRatio) { if (
previous != null &&
amount > previous &&
amount - previous < desired * NPC_PATIENCE.stallRatio
) {
delta = NPC_PATIENCE.roundCost + NPC_PATIENCE.stallPenalty; delta = NPC_PATIENCE.roundCost + NPC_PATIENCE.stallPenalty;
} else if (amount < min) { } else if (amount < min) {
delta = NPC_PATIENCE.roundCost + NPC_PATIENCE.lowballPenalty; delta = NPC_PATIENCE.roundCost + NPC_PATIENCE.lowballPenalty;

View file

@ -168,17 +168,11 @@ export async function createGeneratedNpc(
} }
/** All enabled vendor NPCs that sell the given asset. */ /** All enabled vendor NPCs that sell the given asset. */
export async function findVendorNpcs( export async function findVendorNpcs(payload: PayloadType, assetId: number): Promise<GameNpc[]> {
payload: PayloadType,
assetId: number,
): Promise<GameNpc[]> {
const result = await payload.find({ const result = await payload.find({
collection: "game-npcs", collection: "game-npcs",
where: { where: {
and: [ and: [{ "vendor.enabled": { equals: true } }, { "vendor.sells": { equals: assetId } }],
{ "vendor.enabled": { equals: true } },
{ "vendor.sells": { equals: assetId } },
],
}, },
limit: 100, limit: 100,
depth: 0, depth: 0,
@ -193,10 +187,7 @@ export async function findVendorNpcs(
* 2. Otherwise reuse any existing vendor NPC selling the asset. * 2. Otherwise reuse any existing vendor NPC selling the asset.
* 3. If none exist, generate a new placeholder NPC for the asset. * 3. If none exist, generate a new placeholder NPC for the asset.
*/ */
export async function resolveVendorNpc( export async function resolveVendorNpc(payload: PayloadType, assetId: number): Promise<GameNpc> {
payload: PayloadType,
assetId: number,
): Promise<GameNpc> {
const vendors = await findVendorNpcs(payload, assetId); const vendors = await findVendorNpcs(payload, assetId);
if (vendors.length > 0) { if (vendors.length > 0) {
const inGame = vendors.filter((npc) => npc.isInGame === true); const inGame = vendors.filter((npc) => npc.isInGame === true);

View file

@ -10,10 +10,7 @@ export type StorageRulesSource = Pick<
"allowedStorage" | "prohibitedStorage" | "restrictToAllowed" "allowedStorage" | "prohibitedStorage" | "restrictToAllowed"
>; >;
export type StorageRuleViolation = export type StorageRuleViolation = "prohibited" | "not_whitelisted" | "over_cap";
| "prohibited"
| "not_whitelisted"
| "over_cap";
export interface StorageRuleCheck { export interface StorageRuleCheck {
allowed: boolean; allowed: boolean;
@ -35,10 +32,7 @@ function resolveResourceId(value: number | { id: number }): number {
/** /**
* Whether this resource is on the structure's prohibited list. * Whether this resource is on the structure's prohibited list.
*/ */
export function isResourceProhibited( export function isResourceProhibited(rules: StorageRulesSource, resourceId: number): boolean {
rules: StorageRulesSource,
resourceId: number,
): boolean {
return (rules.prohibitedStorage ?? []).some((rule) => { return (rules.prohibitedStorage ?? []).some((rule) => {
if (!isResourceRef(rule.item)) return false; if (!isResourceRef(rule.item)) return false;
return resolveResourceId(rule.item.value) === resourceId; return resolveResourceId(rule.item.value) === resourceId;
@ -50,10 +44,7 @@ export function isResourceProhibited(
* enabled, only resources listed in `allowedStorage` pass. Otherwise everything * enabled, only resources listed in `allowedStorage` pass. Otherwise everything
* passes (prohibited list still applies separately). * passes (prohibited list still applies separately).
*/ */
export function isResourceWhitelisted( export function isResourceWhitelisted(rules: StorageRulesSource, resourceId: number): boolean {
rules: StorageRulesSource,
resourceId: number,
): boolean {
if (!rules.restrictToAllowed) return true; if (!rules.restrictToAllowed) return true;
return (rules.allowedStorage ?? []).some((rule) => { return (rules.allowedStorage ?? []).some((rule) => {
if (!isResourceRef(rule.item)) return false; if (!isResourceRef(rule.item)) return false;
@ -106,20 +97,14 @@ export function checkStorageDeposit(
/** /**
* Human-readable message describing why a deposit/transfer was rejected. * Human-readable message describing why a deposit/transfer was rejected.
*/ */
export function storageViolationMessage( export function storageViolationMessage(resourceName: string, check: StorageRuleCheck): string {
resourceName: string,
check: StorageRuleCheck,
): string {
switch (check.violation) { switch (check.violation) {
case "prohibited": case "prohibited":
return `This resource is prohibited from storage at this structure.`; return `This resource is prohibited from storage at this structure.`;
case "not_whitelisted": case "not_whitelisted":
return `This structure only accepts items on its allowed storage list — "${resourceName}" is not permitted.`; return `This structure only accepts items on its allowed storage list — "${resourceName}" is not permitted.`;
case "over_cap": { case "over_cap": {
const available = Math.max( const available = Math.max(0, (check.cap ?? 0) - (check.currentStored ?? 0));
0,
(check.cap ?? 0) - (check.currentStored ?? 0),
);
return available <= 0 return available <= 0
? `${resourceName} is at its storage allowance here (${check.cap?.toLocaleString()}). No more can be stored.` ? `${resourceName} is at its storage allowance here (${check.cap?.toLocaleString()}). No more can be stored.`
: `${resourceName} is limited to ${check.cap?.toLocaleString()} units here — you can add at most ${available.toLocaleString()} more.`; : `${resourceName} is limited to ${check.cap?.toLocaleString()} units here — you can add at most ${available.toLocaleString()} more.`;

View file

@ -1,6 +1,6 @@
import { User } from "@/payload-types"; import { User } from "@/payload-types";
export default function hasRoles(roles: NonNullable<User['roles']>, user: User | null | undefined) { export default function hasRoles(roles: NonNullable<User["roles"]>, user: User | null | undefined) {
if (!user) return false; if (!user) return false;
return roles.some((role) => user.roles?.some((urole) => urole === role || urole === "developer")); return roles.some((role) => user.roles?.some((urole) => urole === role || urole === "developer"));

View file

@ -5,7 +5,29 @@ interface GameEventInput {
message: string; message: string;
actor?: number; actor?: number;
structure?: number; structure?: number;
targetCollection?: "users" | "missions" | "maps" | "campaigns" | "factions" | "technologies" | "assets" | "resources" | "structures" | "vehicles" | "game-structures" | "game-vehicles" | "game-npcs" | "shipments" | "bank-accounts" | "bank-transactions" | "ledger-entries" | "locker-storages" | "loadouts" | "market-listings" | "market-negotiations" | "tickets"; targetCollection?:
| "users"
| "missions"
| "maps"
| "campaigns"
| "factions"
| "technologies"
| "assets"
| "resources"
| "structures"
| "vehicles"
| "game-structures"
| "game-vehicles"
| "game-npcs"
| "shipments"
| "bank-accounts"
| "bank-transactions"
| "ledger-entries"
| "locker-storages"
| "loadouts"
| "market-listings"
| "market-negotiations"
| "tickets";
targetId?: number; targetId?: number;
data?: Record<string, unknown>; data?: Record<string, unknown>;
} }