New source found from dndbeyond.com

This commit is contained in:
2026-07-08 01:00:09 -07:00
parent 9a983a6d7b
commit dcefa0d2f2
2865 changed files with 222467 additions and 49053 deletions
@@ -1,6 +1,6 @@
import React, { useCallback } from "react";
import { RollRequest } from "@dndbeyond/dice";
import { RollDicePayload } from "@dndbeyond/pocket-dimension-dice/types";
import LoadingPlaceholder from "../../LoadingPlaceholder";
import { DataLoadingStatusEnum } from "../../componentConstants";
@@ -14,7 +14,7 @@ export interface DiceRollProps {
rollKey: string;
nextRollKey: string | null;
rollTotal: number | null;
diceRollRequest: RollRequest;
diceRollRequest: RollDicePayload["data"];
onChange?: (
key: string,
newValue: string | null,
@@ -25,7 +25,7 @@ export interface DiceRollProps {
) => void;
onRoll: (
key: string,
diceRollRequest: RollRequest,
diceRollRequest: RollDicePayload["data"],
nextRollKey: string | null
) => void;
rollValues: DiceRollValuesProps["rollValues"];
@@ -87,7 +87,7 @@ const DiceRoll: React.FunctionComponent<DiceRollProps> = ({
}
contentNode = (
<React.Fragment>
<>
<div className={diceTotalClassNames.join(" ")}>
<label className="ddbc-dice-roll__total-label" htmlFor={rollKey}>
{rollTotal ?? "--"}
@@ -107,7 +107,7 @@ const DiceRoll: React.FunctionComponent<DiceRollProps> = ({
rollButtonText={rollButtonText}
selectPlaceholderText={selectPlaceholderText}
/>
</React.Fragment>
</>
);
break;
}
@@ -2,9 +2,11 @@ import React from "react";
import { HtmlSelectOption } from "@dndbeyond/character-rules-engine/es";
import { Select } from "~/components/Select";
import { DataLoadingStatusEnum } from "../../../componentConstants";
import { Button } from "../../../legacy/Button";
import { Select } from "../../../legacy/Select";
import styles from "./styles.module.css";
export interface DiceRollActionNodeProps {
rollKey: string;
@@ -15,7 +17,7 @@ export interface DiceRollActionNodeProps {
rollButtonText?: string;
selectPlaceholderText?: string;
onRoll: () => void;
onChange?: (newValue: string | null) => void;
onChange?: (newValue: string | number) => void;
}
const DiceRollActionNode: React.FunctionComponent<DiceRollActionNodeProps> = ({
rollKey,
@@ -31,11 +33,13 @@ const DiceRollActionNode: React.FunctionComponent<DiceRollActionNodeProps> = ({
if (options?.length && rollTotal !== null) {
return (
<Select
className={styles.select}
id={rollKey}
value={assignedValue}
options={options}
placeholder={selectPlaceholderText}
onChange={onChange}
name={rollKey}
/>
);
}
@@ -0,0 +1,8 @@
import DiceRollActionNode from "./DiceRollActionNode";
//Props typings
export * from "./DiceRollActionNode";
export { DiceRollActionNode };
export default DiceRollActionNode;
@@ -40,7 +40,7 @@ const DiceRollValues: React.FunctionComponent<DiceRollValuesProps> = ({
const classNames: Array<string> = ["ddbc-dice-roll__dice-value"];
return (
<React.Fragment>
<>
{orderedKeptDiceValues.map((rollValue: RollValueContract, idx) => {
return (
<div key={idx} className={classNames.join(" ")}>
@@ -57,7 +57,7 @@ const DiceRollValues: React.FunctionComponent<DiceRollValuesProps> = ({
</div>
);
})}
</React.Fragment>
</>
);
};
@@ -0,0 +1,8 @@
import DiceRollValues from "./DiceRollValues";
//Props typings
export * from "./DiceRollValues";
export { DiceRollValues };
export default DiceRollValues;
@@ -0,0 +1,10 @@
import DiceRoll from "./DiceRoll";
//Props typings
export * from "./DiceRoll";
export * from "./DiceRollValues";
export * from "./DiceRollActionNode";
export { DiceRoll };
export default DiceRoll;
@@ -1,12 +1,27 @@
import React, { useCallback, useMemo } from "react";
import React, { useCallback, useContext, useMemo, useState } from "react";
import {
CampaignUtils,
HelperUtils,
HtmlSelectOption,
RollResultContract,
RollValueContract,
} from "@dndbeyond/character-rules-engine/es";
import { Dice, RollRequest } from "@dndbeyond/dice";
import { Platform } from "@dndbeyond/event-pipeline-lib/shared";
import {
GameLogContext,
isMessage,
useMessageBroker,
} from "@dndbeyond/game-log-components";
import { DiceVisibilities } from "@dndbeyond/pocket-dimension-dice/constants";
import { Context as DiceWorkerContext } from "@dndbeyond/pocket-dimension-dice/context";
import { instrumentDiceRoll } from "@dndbeyond/pocket-dimension-dice/helpers/bi/instrumentDiceRoll";
import { rollDice } from "@dndbeyond/pocket-dimension-dice/helpers/rollDice";
import { useUserDiceDataStore } from "@dndbeyond/pocket-dimension-dice/hooks/useUserDiceDataStore";
import { RollDicePayload } from "@dndbeyond/pocket-dimension-dice/types";
import { useAuth } from "~/contexts/Authentication";
import { useCharacterEngine } from "~/hooks/useCharacterEngine";
import { DataLoadingStatusEnum } from "../componentConstants";
import { Button, RemoveButton } from "../legacy";
@@ -44,9 +59,7 @@ export interface DiceRollGroupProps {
onSetRollStatus: (rollKey: string, status: DataLoadingStatusEnum) => void;
rollStatusLookup: Record<string, DataLoadingStatusEnum>;
options?: DiceRollProps["options"];
diceRollRequest:
| DiceRollProps["diceRollRequest"]
| Array<DiceRollProps["diceRollRequest"]>;
diceRollRequest: RollDicePayload["data"] | Array<RollDicePayload["data"]>;
}
const DiceRollGroup: React.FunctionComponent<DiceRollGroupProps> = ({
className = "",
@@ -68,6 +81,24 @@ const DiceRollGroup: React.FunctionComponent<DiceRollGroupProps> = ({
onUpdateDiceRoll,
rollStatusLookup,
}) => {
const { env, hasPddErrored, isPddReady } = useContext(DiceWorkerContext);
const [{ userId }] = useContext(GameLogContext);
const { campaign } = useCharacterEngine();
const gameId = campaign ? String(campaign.id) : undefined;
const dmId = campaign
? String(CampaignUtils.getDmUserId(campaign))
: undefined;
const [groupRolls, setGroupRolls] = useState<
Record<
string,
{
rollKey: string;
properties: Partial<RollResultContract>;
nextRollKey: string | null;
}
>
>({});
const user = useAuth();
const classNames = useMemo<Array<string>>(
() => ["ddbc-dice-roll-group", className],
[className]
@@ -110,8 +141,8 @@ const DiceRollGroup: React.FunctionComponent<DiceRollGroupProps> = ({
});
}, [options, diceRolls, exclusiveOptions, assignedValues]);
const generatedRollRequests = useMemo<Array<RollRequest>>(() => {
let requests: Array<RollRequest> = [];
const generatedRollRequests = useMemo<Array<RollDicePayload["data"]>>(() => {
let requests: Array<RollDicePayload["data"]> = [];
for (let i = 0; i < diceRolls.length; i++) {
if (!Array.isArray(diceRollRequest)) {
requests.push(diceRollRequest);
@@ -130,50 +161,94 @@ const DiceRollGroup: React.FunctionComponent<DiceRollGroupProps> = ({
const handleRoll = useCallback(
(
rollKey: string,
diceRollRequest: RollRequest,
diceRollRequest: RollDicePayload["data"],
nextRollKey: string | null
): void => {
onSetRollStatus(rollKey, DataLoadingStatusEnum.LOADING);
const diceNotation = `${diceRollRequest.rolls[0].diceNotation.set
.map((set) => `${set?.count}${set?.dieType}`)
.join("")}`;
const { data } = rollDice(
{
action: diceRollRequest.action,
diceNotation,
entityId: String(diceRollRequest.context?.entityId),
entityType: String(diceRollRequest.context?.entityType),
gameId,
rollType: diceRollRequest.rolls[0].rollType,
setId: String(
useUserDiceDataStore.getState().getUserDiceData(Number(userId))
?.setId
),
userId,
avatarUrl: diceRollRequest.context?.avatarUrl,
name: diceRollRequest.context?.name,
operand: diceRollRequest.rolls[0].diceNotation.set[0]?.operand,
dmId,
},
hasPddErrored,
isPddReady,
(eventPayload) =>
instrumentDiceRoll(
user,
eventPayload,
Platform.Web,
"characterBuilderRollGroup",
campaign?.id,
undefined,
env
)
);
Dice.roll(diceRollRequest)
.then((result) => {
//RollResult | undefined - RollResult is not exported from Dice;
// only expect to have one single rollRequest.
const rollResult = result.rolls[0].result ?? null;
const rollValues = DiceComponentUtils.generateRollValueContracts(data);
if (!rollResult) {
throw new Error("error in rollResult");
}
if (!rollValues) {
throw new Error("error in rollResult values");
}
const rollValues =
DiceComponentUtils.generateRollValueContracts(result);
const newGroupRoll = {
rollKey,
properties: {
rollValues,
rollTotal: data.rolls[0].result?.total,
},
nextRollKey,
};
if (!rollValues) {
throw new Error("error in rollResult values");
}
setGroupRolls((prevState) => ({
...prevState,
[String(data?.rollId)]: newGroupRoll,
}));
//update status
onSetRollStatus(rollKey, DataLoadingStatusEnum.LOADED);
if (
data.rollId &&
useUserDiceDataStore.getState().getUserDiceData(Number(userId))
?.settings.visibility === DiceVisibilities.Disabled
) {
//update status
onSetRollStatus(newGroupRoll.rollKey, DataLoadingStatusEnum.LOADED);
//update diceRoll
onUpdateDiceRoll(
rollKey,
{ rollValues, rollTotal: rollResult.total },
nextRollKey
);
})
.catch((error: Error) => {
//this could handle different errors types from dice package or thrown errors from result
onSetRollStatus(rollKey, DataLoadingStatusEnum.NOT_LOADED);
if (onRollError) {
onRollError(error.message);
}
console.log("roll error", error);
});
//update diceRoll
onUpdateDiceRoll(
newGroupRoll.rollKey,
newGroupRoll.properties,
newGroupRoll.nextRollKey
);
} else {
onSetRollStatus(rollKey, DataLoadingStatusEnum.LOADING);
}
},
[]
[
campaign?.id,
dmId,
env,
gameId,
hasPddErrored,
isPddReady,
onSetRollStatus,
onUpdateDiceRoll,
user,
userId,
]
);
const handleChange = useCallback(
@@ -220,6 +295,32 @@ const DiceRollGroup: React.FunctionComponent<DiceRollGroupProps> = ({
}
}, [onRemoveGroup, groupKey, nextGroupKey]);
useMessageBroker(
useCallback(
(message) => {
if (
isMessage(message) &&
message.eventType === "dice/roll/fulfilled" &&
groupRolls[message.data.rollId]
) {
//update status
onSetRollStatus(
groupRolls[message.data.rollId].rollKey,
DataLoadingStatusEnum.LOADED
);
//update diceRoll
onUpdateDiceRoll(
groupRolls[message.data.rollId].rollKey,
groupRolls[message.data.rollId].properties,
groupRolls[message.data.rollId].nextRollKey
);
}
},
[groupRolls, onSetRollStatus, onUpdateDiceRoll]
)
);
return (
<div className={classNames.join(" ")}>
<div className="ddbc-dice-roll-group__actions">
@@ -0,0 +1,7 @@
import DiceRoll from "./DiceRoll";
import DiceRollGroup from "./DiceRollGroup";
export * from "./DiceRollGroup";
export { DiceRollGroup, DiceRoll };
export default DiceRollGroup;