Skip to content

Commit

Permalink
Merge pull request #2 from brazucas/feat/ox_inventory_support
Browse files Browse the repository at this point in the history
feat: ox inventory support
  • Loading branch information
pedropapa authored Sep 28, 2024
2 parents 96138d4 + 6f45dec commit 9433e0f
Show file tree
Hide file tree
Showing 29 changed files with 162 additions and 48 deletions.
46 changes: 38 additions & 8 deletions brz-core/client/thirdparties.service.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,42 @@
declare const SETTINGS: any;

const adapters: {
[key in string]: {
isEnabled: boolean;
hasItem: (itemName: string) => boolean;
notify: (message: string, type: "success" | "error") => void;
useItemHookName: string;
useItemHookHandler: (...params: any) => {
itemName: string;
itemType: string;
};
};
} = {
qbCore: {
isEnabled: !!exports["qb-core"]?.GetCoreObject()?.Functions?.HasItem,
hasItem: (itemName: string) =>
!!exports["qb-core"].GetCoreObject().Functions.HasItem(itemName),
!!exports["qb-core"].GetCoreObject?.().Functions.HasItem(itemName),
notify: (message: string, type: "success" | "error") => {
exports["qb-core"].GetCoreObject().Functions.Notify(message, type);
exports["qb-core"].GetCoreObject?.().Functions.Notify(message, type);
},
useItemHookName: "inventory:client:ItemBox",
useItemHookHandler: (itemData: any, type: "use" | string) => ({
itemName: itemData.name,
itemType: type,
}),
},
ox_inventory: {
hasItem: (itemName: string) =>
exports["ox_inventory"].GetItemCount(itemName) > 0,
notify: (message: string, type: "success" | "error") =>
TriggerEvent("ox_lib:notify", {
title: "Fishing",
description: message,
type,
}),
useItemHookName: "ox_inventory:usedItem",
useItemHookHandler: (item: string[], slotId: number, metadata: any) => ({
itemName: item[0],
itemType: "use",
}),
},
};

Expand All @@ -20,12 +45,17 @@ export const hasItem = (itemName: string) => getAdapter().hasItem(itemName);
export const notify = (message: string, type: "success" | "error") =>
getAdapter().notify(message, type);

export const getUseItemHookName = (): string => getAdapter().useItemHookName;

export const getUseItemHookHandler = () => getAdapter().useItemHookHandler;

const getAdapter = () => {
const enabledAdapterName = Object.keys(adapters).find(
(adapterName) => adapters[adapterName].isEnabled
);
const enabledAdapterName = SETTINGS.INVENTORY_SYSTEM || "ox_inventory";

if (!enabledAdapterName) throw new Error("No enabled adapter found");
if (!adapters[enabledAdapterName])
throw new Error(
`FATAL: ${enabledAdapterName} is not supported, please check the documentation for supported inventory systems`
);

return adapters[enabledAdapterName];
};
88 changes: 53 additions & 35 deletions brz-core/server/thirdparties.service.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,17 @@
type InventoryItem = {
weight: number;
unique: boolean;
name: string;
type: string;
description: string;
label: string;
combinable: boolean;
useable: boolean;
shouldClose: boolean;
image: string;
};
import { Adapter } from "../types/thirdparties.types";

declare const SETTINGS: any;

const qbCoreGetPlayer = () =>
SETTINGS.INVENTORY_SYSTEM === "qbCore" &&
exports["qb-core"]?.GetCoreObject?.()?.Functions?.GetPlayer;

const adapters: {
[key in string]: {
isEnabled: boolean;
removeItem: (source: number, itemName: string) => boolean;
addItem: (source: number, itemName: string) => boolean;
getItem: (itemName: string) => InventoryItem;
notify: (
source: number,
message: string,
type: "success" | "error"
) => void;
};
[key in string]: Adapter;
} = {
qbCore: {
isEnabled: !!exports["qb-core"]?.GetCoreObject()?.Functions?.RemoveItem,
removeItem: (source: number, itemName: string) => {
const player = qbCoreGetPlayer(source);
const player = qbCoreGetPlayer()(source);

if (!player) {
console.error("Player not found ", source, itemName);
Expand All @@ -38,7 +22,7 @@ const adapters: {
return true;
},
addItem: (source: number, itemName: string) => {
const player = qbCoreGetPlayer(source);
const player = qbCoreGetPlayer()(source);

if (!player) {
console.error("Player not found ", source, itemName);
Expand All @@ -50,12 +34,12 @@ const adapters: {
},
getItem: (itemName: string) => {
const item =
exports["qb-core"]?.GetCoreObject()?.Shared?.Items?.[itemName];
exports["qb-core"]?.GetCoreObject?.()?.Shared?.Items?.[itemName];

return item;
},
notify: (source: number, message: string, type: "success" | "error") => {
const player = qbCoreGetPlayer(source);
const player = qbCoreGetPlayer()(source);

if (!player) {
console.error("Player not found");
Expand All @@ -71,11 +55,44 @@ const adapters: {
return true;
},
},
ox_inventory: {
removeItem: (source: number, itemName: string) => {
exports["ox_inventory"].RemoveItem(source, itemName, 1);
return true;
},
addItem: (source: number, itemName: string) => {
exports["ox_inventory"].AddItem(source, itemName, 1);
return true;
},
getItem: (itemName: string) => {
const item = exports["ox_inventory"].Items(itemName);

if (!item) return null;

const { name, weight, label, stack, consume, client = null } = item;

return {
weight,
unique: false,
name,
type: "item",
description: name,
label,
combinable: stack,
useable: consume,
shouldClose: false,
image: client?.image,
};
},
notify: (source: number, message: string, type: "success" | "error") =>
TriggerClientEvent("ox_lib:notify", source, {
title: "Fishing",
description: message,
type,
}),
},
};

const qbCoreGetPlayer =
exports["qb-core"]?.GetCoreObject()?.Functions?.GetPlayer;

export const addItem = (source: number, itemName: string) =>
getAdapter().addItem(source, itemName);

Expand All @@ -91,11 +108,12 @@ export const notify = (
) => getAdapter().notify(source, message, type);

const getAdapter = () => {
const enabledAdapterName = Object.keys(adapters).find(
(adapterName) => adapters[adapterName].isEnabled
);
const enabledAdapterName = SETTINGS.INVENTORY_SYSTEM || "ox_inventory";

if (!enabledAdapterName) throw new Error("No enabled adapter found");
if (!adapters[enabledAdapterName])
throw new Error(
`FATAL: ${enabledAdapterName} is not supported, please check the documentation for supported inventory systems`
);

return adapters[enabledAdapterName];
};
19 changes: 19 additions & 0 deletions brz-core/types/thirdparties.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export type Adapter = {
removeItem: (source: number, itemName: string) => boolean;
addItem: (source: number, itemName: string) => boolean;
getItem: (itemName: string) => InventoryItem | null;
notify: (source: number, message: string, type: "success" | "error") => void;
};

type InventoryItem = {
weight: number;
unique: boolean;
name: string;
type: string;
description: string;
label: string;
combinable: boolean;
useable: boolean;
shouldClose: boolean;
image: string;
};
1 change: 0 additions & 1 deletion client/actions/baiting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ const startBaitingOpportunity = () => {
baitingOpportunityTickInterval = setInterval(baitingOpportunityTick, 10);

detectBaitCatchTick = setTick(async () => {
console.log("detectBaitCatchTick");
if (IsControlJustPressed(0, 46)) {
SendNUIMessage({
action: "hide-baiting-tooltips",
Expand Down
10 changes: 8 additions & 2 deletions client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import { Fish } from "@common/types";
import { requestStartFishing, startFishing } from "./fishing";
import { getState, setState } from "./state";
import { t } from "@config/locales";
import {
getUseItemHookName,
getUseItemHookHandler,
} from "@core/thirdparties.service";

RegisterCommand(
t("fish_command"),
Expand All @@ -22,8 +26,10 @@ onNet("brz-fishing:startFishing", (fishId: keyof Fish) =>
startFishing(GetPlayerServerId(PlayerId()), fishId)
);

onNet("inventory:client:ItemBox", (itemData: any, type: "use" | string) => {
if (type === "use" && itemData.name === "fishingrod1") {
onNet(getUseItemHookName(), (...params: any) => {
const { itemName, itemType } = getUseItemHookHandler()(params);

if (itemType === "use" && itemName === "fishingrod1") {
changeFishingState();
}
});
Expand Down
15 changes: 14 additions & 1 deletion client/test/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ global.PlayerId = jest.fn(() => 1);

import { requestStartFishing, startFishing } from "@/fishing";
import { getState, setState } from "@/state";
import { getUseItemHookName } from "@core/thirdparties.service";

jest.mock("@config/locales", () => ({
t: jest.fn().mockImplementation((phase: string) => {
Expand All @@ -33,6 +34,14 @@ jest.mock("../state", () => ({
setState: jest.fn(),
}));

jest.mock("@core/thirdparties.service", () => ({
getUseItemHookName: jest.fn().mockReturnValue("inventory:client:ItemBox"),
getUseItemHookHandler: jest.fn().mockReturnValue(() => ({
itemName: "fishingrod1",
itemType: "use",
})),
}));

describe("client", () => {
beforeAll(() => {
require("../client");
Expand Down Expand Up @@ -78,7 +87,11 @@ describe("client", () => {
(setState as jest.Mock).mockReset();
(requestStartFishing as jest.Mock).mockReset();
});
it("should register an onNet event for inventory:client:ItemBox", () => {
it("should register an onNet event for the third party adapter", () => {
(getUseItemHookName as jest.Mock).mockReturnValue(
"inventory:client:ItemBox"
);

expect(global.onNet).toBeCalledWith(
"inventory:client:ItemBox",
expect.any(Function)
Expand Down
5 changes: 5 additions & 0 deletions fxmanifest.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ game 'gta5'

shared_scripts {
'settings.js',
'@ox_lib/init.lua',
}

ox_libs {
'interface',
}

server_script 'dist/server/**/*.js'
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added installation/ox-inventory/web/images/dolphin.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added installation/ox-inventory/web/images/fish.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added installation/ox-inventory/web/images/humpback.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added installation/ox-inventory/web/images/stingray.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion nui/fishing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ const actionHandlers: {
const { param, value } = event.data as EmitFishingSetParamAction;
paramsHandlers[
param as keyof Omit<FishingParam, "baseLineTension" | "fishId">
](value);
]?.(value);
},
"fish-2d-position": (event: any) => {
const { center, posX, posY } = event.data as EmitFish2DPositionAction;
Expand Down
7 changes: 7 additions & 0 deletions server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ export const processCatchFishEvent = (playerId: PlayerId) => {

const itemInfo = getItem(fish.itemName);

if (!itemInfo) {
console.error(
`ERROR: Item ${fish.itemName} does not exist. Please be sure you added all fishing items to your inventory system.`
);
return;
}

addItem(playerId, fish.itemName);
notify(
playerId,
Expand Down
16 changes: 16 additions & 0 deletions server/test/server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,22 @@ describe("brz-fishing server-side script", () => {
"success"
);
});

it("should log an error message when item is not found", () => {
const consoleError = jest.spyOn(global.console, "error");

(getItem as jest.Mock).mockReturnValueOnce(null);

processRequestStartFishing(1);

processCatchFishEvent(1);

expect(consoleError).toHaveBeenCalledWith(
expect.stringMatching(
/ERROR: Item (.*?) does not exist. Please be sure you added all fishing items to your inventory system./
)
);
});
});

describe("processUseBaitEvent", () => {
Expand Down
1 change: 1 addition & 0 deletions settings.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const SETTINGS = {
INVENTORY_SYSTEM: "ox_inventory", // ox_inventory or qbCore
DEFAULT_LANG: "en-us",
MAXIMUM_LINE_TENSION: 100,
LINE_TENSION_INCREASE_RATE: 5,
Expand Down

0 comments on commit 9433e0f

Please sign in to comment.