Skip to content

Commit

Permalink
feat!: switch to new Fantasy Statblocks API
Browse files Browse the repository at this point in the history
  • Loading branch information
valentine195 committed Mar 5, 2024
1 parent 7a3e870 commit 28c8363
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 52 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"dotenv": "^16.3.1",
"esbuild": "^0.19.3",
"esbuild-svelte": "^0.8.0",
"fantasy-statblocks": "^4.0.1",
"fantasy-statblocks": "^4.0.3",
"fast-copy": "^3.0.1",
"jest": "^29.7.0",
"obsidian": "^1.4.11",
Expand Down
37 changes: 29 additions & 8 deletions src/builder/view.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ItemView, type ViewStateResult, WorkspaceLeaf } from "obsidian";
import type InitiativeTracker from "src/main";
import { BUILDER_VIEW } from "../utils";
import { BUILDER_VIEW, buildLoader } from "../utils";

import Builder from "./view/Builder.svelte";
import { encounter } from "./stores/encounter";
Expand Down Expand Up @@ -37,15 +37,36 @@ export default class BuilderView extends ItemView {
}
ui: Builder;
async onOpen() {
this.ui = new Builder({
target: this.contentEl,
props: {
plugin: this.plugin
}
});

if (
this.plugin.canUseStatBlocks &&
!window["FantasyStatblocks"].isResolved()
) {
this.contentEl.addClasses(["waiting-for-bestiary", "is-loading"]);
const loading = this.contentEl.createEl("p", {
text: "Waiting for Fantasy Statblocks Bestiary..."
});
window["FantasyStatblocks"].onResolved(() => {
this.contentEl.removeClasses(["waiting-for-bestiary", "is-loading"]);
loading.detach();
this.ui = new Builder({
target: this.contentEl,
props: {
plugin: this.plugin
}
});
});
} else {
this.ui = new Builder({
target: this.contentEl,
props: {
plugin: this.plugin
}
});
}
}
async onClose() {
this.ui.$destroy();
this.ui?.$destroy();
}
getDisplayText(): string {
return "Encounter Builder";
Expand Down
3 changes: 2 additions & 1 deletion src/builder/view/creatures/Creatures.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import type InitiativeTracker from "src/main";
import Ajv from "ajv";
import schema from "../../stores/filter/filter-schema.json";
import type { BuilderState } from "obsidian-overload";
const table = getContext<BuiltTableStore>("table");
const { sortDir, allHeaders } = table;
Expand Down Expand Up @@ -62,7 +63,7 @@
const ajv = new Ajv();
// validate is a type guard for MyData - type is inferred from schema type
const validate = ajv.compile(schema);
const validate = ajv.compile<BuilderState>(schema);
const input = createEl("input", {
attr: {
type: "file",
Expand Down
10 changes: 6 additions & 4 deletions src/encounter/ui/Creature.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import type InitiativeTracker from "src/main";
import { FRIENDLY, HIDDEN, RANDOM_HP, getRpgSystem } from "src/utils";
import type { Creature } from "src/utils/creature";
import { getContext } from "svelte/internal";
import { getContext } from "svelte";
const plugin = getContext<InitiativeTracker>("plugin");
const rpgSystem = getRpgSystem(plugin);
Expand Down Expand Up @@ -34,9 +34,9 @@
{/if}
<span class="creature-name" on:click={() => plugin.openCombatant(creature)}>
{#if creature.display && creature.display != creature.name}
&nbsp;{creature.display}{count == 1 ? "" : "s"} ({creature.name})
{creature.display}{count == 1 ? "" : "s"} ({creature.name})
{:else}
&nbsp;{creature.name}{count == 1 ? "" : "s"}
{creature.name}{count == 1 ? "" : "s"}
{/if}
{#if shouldShowRoll && creature.hit_dice?.length}
<span class="has-icon" aria-label="Rolling for HP" use:rollEl />
Expand All @@ -46,7 +46,9 @@
<span class="xp-parent">
<span class="paren left">&nbsp;(</span>
<span class="xp-container">
<span class="xp number">{rpgSystem.formatDifficultyValue(xp)}</span>
<span class="xp number"
>{rpgSystem.formatDifficultyValue(xp)}</span
>
<span class="xp text">{rpgSystem.valueUnit}</span>
</span>
<span class="paren right">)</span>
Expand Down
25 changes: 13 additions & 12 deletions src/encounter/ui/EncounterLine.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -121,20 +121,21 @@
<span>
{#if creatures.size}
{#each [...creatures] as [creature, count], index}
<span aria-label={label(creature)}>
{joiner(index, creatures.size)}
<strong use:rollerEl={creature} />&nbsp;
<span
<span aria-label={label(creature)}
>{joiner(index, creatures.size)}<strong
use:rollerEl={creature}
/> <span
class="creature-name"
on:click={() => plugin.openCombatant(creature)}
>
{#if creature.display && creature.display != creature.name}
{creature.display}{count == 1 ? "" : "s"} ({creature.name})
{:else}
{creature.name}{count == 1 ? "" : "s"}
{/if}
</span>
</span>
>{#if creature.display && creature.display != creature.name}{creature.display}{count ==
1
? ""
: "s"} ({creature.name}){:else}{creature.name}{count ==
1
? ""
: "s"}{/if}</span
></span
>
{/each}
{:else}
-
Expand Down
37 changes: 37 additions & 0 deletions src/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,40 @@ body {
align-items: center;
gap: 0.25rem;
}

.waiting-for-bestiary.is-loading {
display: flex;
justify-content: center;
font-style: italic;
color: var(--text-muted);
}

.waiting-for-bestiary.inline {
display: flex;
align-items: center;
gap: 0.25rem;
font-size: var(--font-small);
--icon-size: var(--icon-s);
}

.waiting-for-bestiary.inline .icon {
display: flex;
align-items: center;
animation: rotation 1s ease infinite;
}


@keyframes rotation {
0% {
transform: scale(1) rotate(-60deg);
}
20% {
transform: /* scale(1.1) */ rotate(-90deg);
}
50% {
transform: /* scale(0.9) */ rotate(690deg);
}
100% {
transform: /* scale(1) */ rotate(660deg);
}
}
125 changes: 103 additions & 22 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
parseYaml,
Plugin,
TFile,
WorkspaceLeaf
WorkspaceLeaf,
setIcon
} from "obsidian";

import {
Expand Down Expand Up @@ -153,9 +154,10 @@ export default class InitiativeTracker extends Plugin {
}

get canUseStatBlocks(): boolean {
return true;
if (this.app.plugins.enabledPlugins.has("obsidian-5e-statblocks")) {
return (window["FantasyStatblocks"]?.getVersion()?.major ?? 0) >= 4;
}
}
return false;
}
get statblockVersion() {
Expand Down Expand Up @@ -281,7 +283,9 @@ export default class InitiativeTracker extends Plugin {
e.createEl("p", {
text: `Initiative Tracker v${this.manifest.version} requires Fantasy Statblocks v4.0.0 or later.`
});
e.createEl("span", { text: "Please update Fantasy Statblocks to use the Fantasy Statblocks integration."})
e.createEl("span", {
text: "Please update Fantasy Statblocks to use the Fantasy Statblocks integration."
});
})
);
}
Expand Down Expand Up @@ -314,14 +318,49 @@ export default class InitiativeTracker extends Plugin {

this.registerEditorSuggest(new EncounterSuggester(this));
this.registerMarkdownCodeBlockProcessor("encounter", (src, el, ctx) => {
const handler = new EncounterBlock(this, src, el);
ctx.addChild(handler);
if (
this.canUseStatBlocks &&
!window["FantasyStatblocks"].isResolved()
) {
el.addClasses(["waiting-for-bestiary", "is-loading"]);
const loading = el.createEl("p", {
text: "Waiting for Fantasy Statblocks Bestiary..."
});
window["FantasyStatblocks"].onResolved(() => {
el.removeClasses(["waiting-for-bestiary", "is-loading"]);
loading.detach();
const handler = new EncounterBlock(this, src, el);
ctx.addChild(handler);
});
} else {
const handler = new EncounterBlock(this, src, el);
ctx.addChild(handler);
}
});
this.registerMarkdownCodeBlockProcessor(
"encounter-table",
(src, el, ctx) => {
const handler = new EncounterBlock(this, src, el, true);
ctx.addChild(handler);
if (
this.canUseStatBlocks &&
!window["FantasyStatblocks"].isResolved()
) {
el.addClasses(["waiting-for-bestiary", "is-loading"]);
const loading = el.createEl("p", {
text: "Waiting for Fantasy Statblocks Bestiary..."
});
window["FantasyStatblocks"].onResolved(() => {
el.removeClasses([
"waiting-for-bestiary",
"is-loading"
]);
loading.detach();
const handler = new EncounterBlock(this, src, el, true);
ctx.addChild(handler);
});
} else {
const handler = new EncounterBlock(this, src, el, true);
ctx.addChild(handler);
}
}
);

Expand All @@ -337,25 +376,67 @@ export default class InitiativeTracker extends Plugin {
if (!codes.length) return;

for (const code of codes) {
const definitions = code.innerText.replace(`encounter:`, "");
const target = createSpan("initiative-tracker-encounter-line");

const creatures = parseYaml("[" + definitions.trim() + "]");
const parser = new EncounterParser(this);
const parsed = await parser.parse({ creatures });
code.replaceWith(target);

if (!parsed || !parsed.creatures || !parsed.creatures.size)
continue;
const buildEncounter = async () => {
const definitions = code.innerText.replace(
`encounter:`,
""
);

const target = createSpan("initiative-tracker-encounter-line");
new EncounterLine({
target,
props: {
...parsed,
plugin: this
}
});
const creatures = parseYaml("[" + definitions.trim() + "]");
const parser = new EncounterParser(this);
const parsed = await parser.parse({ creatures });

code.replaceWith(target);
if (
!parsed ||
!parsed.creatures ||
!parsed.creatures.size
) {
target.setText("No creatures found.");
return;
}
new EncounterLine({
target,
props: {
...parsed,
plugin: this
}
});
};
if (
true
/* this.canUseStatBlocks &&
!window["FantasyStatblocks"].isResolved() */
) {
const loading = target.createSpan(
"waiting-for-bestiary inline"
);
const delay = Math.floor(200 * Math.random());
console.log("🚀 ~ file: main.ts:417 ~ duration:", delay);

setIcon(
loading.createDiv({
cls: "icon",
attr: {
style: `animation-delay: ${delay}ms`
}
}),
"loader-2"
);
loading.createEl("em", {
text: "Loading Bestiary..."
});
window["FantasyStatblocks"].onResolved(() => {
el.removeClasses(["waiting-for-bestiary", "inline"]);
loading.detach();
buildEncounter();
});
} else {
buildEncounter();
}
}
});

Expand Down
Loading

0 comments on commit 28c8363

Please sign in to comment.