diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e6428f0..043b76c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -7,10 +7,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Use Node.js v22
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v4
with:
node-version: "22.x"
registry-url: "https://registry.npmjs.org"
@@ -20,7 +20,7 @@ jobs:
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Get Cache
- uses: actions/cache@v2
+ uses: actions/cache@v4
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
@@ -38,10 +38,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Use Node.js v22
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v4
with:
node-version: "22.x"
registry-url: "https://registry.npmjs.org"
@@ -51,7 +51,7 @@ jobs:
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Get Cache
- uses: actions/cache@v2
+ uses: actions/cache@v4
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
@@ -69,10 +69,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Use Node.js v22
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v4
with:
node-version: "22.x"
registry-url: "https://registry.npmjs.org"
@@ -82,7 +82,7 @@ jobs:
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Get Cache
- uses: actions/cache@v2
+ uses: actions/cache@v4
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
@@ -100,10 +100,10 @@ jobs:
# runs-on: ubuntu-latest
# steps:
# - name: Checkout Repository
- # uses: actions/checkout@v2
+ # uses: actions/checkout@v4
# - name: Use Node.js v22
- # uses: actions/setup-node@v2
+ # uses: actions/setup-node@v4
# with:
# node-version: '16.x'
# registry-url: 'https://registry.npmjs.org'
@@ -132,7 +132,7 @@ jobs:
needs: [build, format, lint]
steps:
- name: Use NodeJS v16
- uses: actions/setup-node@v2
+ uses: actions/setup-node@v4
with:
node-version: "16"
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index ff6ac17..116e9aa 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -10,7 +10,7 @@ jobs:
environment: production
steps:
- name: Checkout Repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
- name: Get temporary file for SSH key
id: mktemp
diff --git a/public/css/questlog.css b/public/css/questlog.css
index 65905a3..eedd706 100644
--- a/public/css/questlog.css
+++ b/public/css/questlog.css
@@ -137,3 +137,43 @@ textarea.form-input {
overflow-y: auto;
overflow-x: hidden;
}
+
+.input-group {
+ align-items: flex-start;
+}
+
+.input-group .input-group-addon {
+ height: 1.8rem;
+ display: flex;
+ align-items: center;
+ margin-top: 0;
+}
+
+.input-group > .objective-list,
+.input-group > .card {
+ flex: 1 1 auto;
+ width: 100%;
+}
+
+.objective-list {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.objective-list .d-flex {
+ align-items: flex-start;
+ width: 100%;
+}
+
+.objective-list .btn-action {
+ margin-top: 0.1rem;
+ margin-left: 0.5rem !important;
+}
+
+.input-group .popover {
+ margin-top: 0;
+ height: 1.8rem;
+ display: flex;
+ align-items: center;
+}
diff --git a/public/script/questlog.tsx b/public/script/questlog.tsx
index 0d1cf29..2b5d37c 100644
--- a/public/script/questlog.tsx
+++ b/public/script/questlog.tsx
@@ -2,16 +2,8 @@
import { _createElement, _fragment } from "simple-jsx-handler";
declare const React: JSX.IntrinsicElements;
-import {
- Objective,
- OBJECTIVE_TYPES,
- ObjectiveDisplay,
- Quest,
- Renderable,
- Reward,
- REWARD_TYPES,
- RewardDisplay,
-} from "./questlog/types";
+import { Objective, ObjectiveDisplay, Quest, Renderable, Reward, RewardDisplay } from "./questlog/types";
+import { OBJECTIVE_TYPES, REWARD_TYPES } from "./questlog/definitions";
import { createField } from "./questlog/field";
import { removeNode } from "./util";
import { SOUNDS } from "./questlog/data";
diff --git a/public/script/questlog/definitions.tsx b/public/script/questlog/definitions.tsx
new file mode 100644
index 0000000..d139f76
--- /dev/null
+++ b/public/script/questlog/definitions.tsx
@@ -0,0 +1,508 @@
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { _createElement, _fragment } from "simple-jsx-handler";
+declare const React: JSX.IntrinsicElements;
+
+import {
+ BIOMES,
+ BLOCKS_TAGS,
+ DIMENSIONS,
+ EFFECTS,
+ ENCHANTMENTS,
+ ENTITIES,
+ ITEMS,
+ ITEMS_TAGS,
+ LOOT_TABLES,
+ STATS,
+} from "./data";
+import { TypeDefinition } from "./types";
+
+export const OBJECTIVE_TYPES: TypeDefinition[] = [
+ {
+ type: "questlog:stat",
+ description: <>Uses the player's statistics to track progress>,
+ additional: [
+ {
+ key: "stat",
+ name: "Statistic",
+ optional: false,
+ type: "input",
+ description: <>The statistic to track>,
+ autocomplete: STATS,
+ },
+ {
+ key: "trackSinceStart",
+ name: "Should track since start?",
+ optional: true,
+ type: "boolean",
+ description: (
+ <>
+ If true, the stat's value will be tracked since the creation of the quest.
+
+ If false, the stat's value will be the player's total stat value.
+ >
+ ),
+ },
+ ],
+ },
+ {
+ type: "questlog:quest_complete",
+ description: <>Tracks this quest to be completed, useful for adding dependency quests.>,
+ additional: [
+ {
+ key: "quest",
+ name: "Quest",
+ description: <>The quest to track>,
+ type: "input",
+ optional: false,
+ },
+ ],
+ },
+ {
+ type: "questlog:block_mine",
+ description: <>Tracks the number of blocks mined by the player>,
+ additional: [
+ {
+ key: "block",
+ name: "Block",
+ description: (
+ <>
+ The block to track.
+
+ May be the block itself or a tag prefixed with #.
+ >
+ ),
+ type: "input",
+ optional: false,
+ autocomplete: BLOCKS_TAGS,
+ },
+ ],
+ },
+ {
+ type: "questlog:block_place",
+ description: <>Tracks the number of blocks placed by the player>,
+ additional: [
+ {
+ key: "block",
+ name: "Block",
+ description: (
+ <>
+ The block to track.
+
+ May be the block itself or a tag prefixed with #.
+ >
+ ),
+ type: "input",
+ optional: false,
+ autocomplete: BLOCKS_TAGS,
+ },
+ ],
+ },
+ {
+ type: "questlog:entity_approach",
+ description: <>Tracks the number of times the player approaches a specific entity>,
+ additional: [
+ {
+ key: "entity",
+ name: "Entity",
+ description: <>The entity to track.>,
+ type: "input",
+ optional: false,
+ autocomplete: ENTITIES,
+ },
+ {
+ key: "range",
+ name: "Range",
+ description: <>The range to track the entity in>,
+ type: "input",
+ isNumber: true,
+ optional: false,
+ },
+ ],
+ },
+ {
+ type: "questlog:entity_breed",
+ description: <>Tracks the number of times the player breeds entities>,
+ additional: [
+ {
+ key: "entity",
+ name: "Entity",
+ description: <>The entity to track.>,
+ type: "input",
+ optional: false,
+ autocomplete: ENTITIES,
+ },
+ ],
+ },
+ {
+ type: "questlog:entity_death",
+ description: <>Tracks the number of times the player dies to a specific entity>,
+ additional: [
+ {
+ key: "entity",
+ name: "Entity",
+ description: <>The entity to track.>,
+ type: "input",
+ optional: false,
+ autocomplete: ENTITIES,
+ },
+ ],
+ },
+ {
+ type: "questlog:entity_kill",
+ description: <>Tracks the number of a specific export type of entity the player kills>,
+ additional: [
+ {
+ key: "entity",
+ name: "Entity",
+ description: <>The entity to track.>,
+ type: "input",
+ optional: false,
+ autocomplete: ENTITIES,
+ },
+ ],
+ },
+ {
+ type: "questlog:item_craft",
+ description: <>Tracks the number of a specific item the player crafts>,
+ additional: [
+ {
+ key: "item",
+ name: "Item",
+ description: (
+ <>
+ The item to track.
+
+ May be the item itself or a tag prefixed with #.
+ >
+ ),
+ type: "input",
+ optional: false,
+ autocomplete: ITEMS_TAGS,
+ },
+ ],
+ },
+ {
+ type: "questlog:item_drop",
+ description: <>Tracks the number of a specific item the player drops>,
+ additional: [
+ {
+ key: "item",
+ name: "Item",
+ description: (
+ <>
+ The item to track.
+
+ May be the item itself or a tag prefixed with #.
+ >
+ ),
+ type: "input",
+ optional: false,
+ autocomplete: ITEMS_TAGS,
+ },
+ ],
+ },
+ {
+ type: "questlog:item_equip",
+ description: <>Tracks the number of times the player equips a specific item>,
+ additional: [
+ {
+ key: "item",
+ name: "Item",
+ description: (
+ <>
+ The item to track.
+
+ May be the item itself or a tag prefixed with #.
+ >
+ ),
+ type: "input",
+ optional: false,
+ autocomplete: ITEMS_TAGS,
+ },
+ {
+ key: "slot",
+ name: "Slot",
+ description: <>The slot to track.>,
+ type: "select",
+ optional: false,
+ options: ["mainhand", "offhand", "feet", "legs", "chest", "head"],
+ },
+ ],
+ },
+ {
+ type: "questlog:item_obtain",
+ description: <>Tracks the number of a specific item the player has in their inventory>,
+ additional: [
+ {
+ key: "item",
+ name: "Item",
+ description: (
+ <>
+ The item to track.
+
+ May be the item itself or a tag prefixed with #.
+ >
+ ),
+ type: "input",
+ optional: false,
+ autocomplete: ITEMS_TAGS,
+ },
+ ],
+ },
+ {
+ type: "questlog:item_pickup",
+ description: <>Tracks the number of a specific item the player picks up>,
+ additional: [
+ {
+ key: "item",
+ name: "Item",
+ description: (
+ <>
+ The item to track.
+
+ May be the item itself or a tag prefixed with #.
+ >
+ ),
+ type: "input",
+ optional: false,
+ autocomplete: ITEMS_TAGS,
+ },
+ ],
+ },
+ {
+ type: "questlog:item_use",
+ description: <>Tracks the number of times the player uses a specific item>,
+ additional: [
+ {
+ key: "item",
+ name: "Item",
+ description: (
+ <>
+ The item to track.
+
+ May be the item itself or a tag prefixed with #.
+ >
+ ),
+ type: "input",
+ optional: false,
+ autocomplete: ITEMS_TAGS,
+ },
+ ],
+ },
+ {
+ type: "questlog:visit_biome",
+ description: <>Tracks the number of times the player visits a specific biome>,
+ additional: [
+ {
+ key: "biome",
+ name: "Biome",
+ description: <>The biome to track.>,
+ type: "input",
+ optional: false,
+ autocomplete: BIOMES,
+ },
+ ],
+ },
+ {
+ type: "questlog:visit_dimension",
+ description: <>Tracks the number of times the player visits a specific dimension>,
+ additional: [
+ {
+ key: "dimension",
+ name: "Dimension",
+ description: <>The dimension to track.>,
+ type: "input",
+ optional: false,
+ autocomplete: DIMENSIONS,
+ },
+ ],
+ },
+ {
+ type: "questlog:trample",
+ description: <>Tracks the number of times the player tramples farmland>,
+ },
+ {
+ type: "questlog:effect_added",
+ description: <>Tracks the number of times the player gains a specific effect>,
+ additional: [
+ {
+ key: "effect",
+ name: "Effect",
+ description: <>The effect to track.>,
+ type: "input",
+ optional: false,
+ autocomplete: EFFECTS,
+ },
+ ],
+ },
+ {
+ type: "questlog:enchant",
+ description: <>Tracks the number of times the player enchants an item with a specific enchantment>,
+ additional: [
+ {
+ key: "enchantment",
+ name: "Enchantment",
+ description: (
+ <>
+ The enchantment to track.
+
+ If not specified, the stat will track any enchantment.
+ >
+ ),
+ type: "input",
+ optional: true,
+ autocomplete: ENCHANTMENTS,
+ },
+ {
+ key: "level",
+ name: "Level",
+ description: <>The minimum level of the enchantment to track>,
+ type: "input",
+ isNumber: true,
+ optional: true,
+ default: "1",
+ },
+ {
+ key: "item",
+ name: "Item",
+ description: (
+ <>
+ The item to track.
+
+ If not specified, the stat will track any item.
+ >
+ ),
+ type: "input",
+ optional: true,
+ autocomplete: ITEMS,
+ },
+ ],
+ },
+ {
+ type: "questlog:not",
+ description: <>Inverts the completion status of a child objective.>,
+ additional: [
+ {
+ key: "objective",
+ name: "Condition",
+ description: <>The objective logic to invert.>,
+ type: "objective",
+ optional: false,
+ default: {
+ type: "questlog:block_mine",
+ block: "minecraft:stone",
+ },
+ },
+ ],
+ },
+ {
+ type: "questlog:or",
+ description: (
+ <>
+ Completes if any of the child objectives are completed.
+ >
+ ),
+ additional: [
+ {
+ key: "objectives",
+ name: "Conditions",
+ description: <>The list of alternative conditions.>,
+ type: "objective_list",
+ optional: false,
+ default: [
+ { type: "questlog:block_mine", block: "minecraft:stone" },
+ { type: "questlog:block_mine", block: "minecraft:dirt" },
+ ],
+ },
+ ],
+ },
+];
+
+export const REWARD_TYPES: TypeDefinition[] = [
+ {
+ type: "questlog:item",
+ description: <>Gives the player an item>,
+ additional: [
+ {
+ key: "item",
+ name: "Item",
+ description: <>The item to give the player>,
+ type: "input",
+ optional: false,
+ autocomplete: ITEMS,
+ },
+ {
+ key: "count",
+ name: "Amount",
+ description: <>The amount of the item to give the player>,
+ default: "1",
+ type: "input",
+ isNumber: true,
+ optional: true,
+ },
+ ],
+ },
+ {
+ type: "questlog:command",
+ description: <>Runs a command as the player>,
+ additional: [
+ {
+ key: "command",
+ name: "Command",
+ description: <>The command to run>,
+ type: "input",
+ optional: false,
+ },
+ {
+ key: "permission_level",
+ name: "Permission Level",
+ description: (
+ <>
+ The command's permission level, when ran as the player.
+
+ The player doesn't need to have this permission level, be careful!
+ >
+ ),
+ default: "2",
+ type: "input",
+ isNumber: true,
+ optional: true,
+ },
+ ],
+ },
+ {
+ type: "questlog:experience",
+ description: <>Gives the player experience>,
+ additional: [
+ {
+ key: "experience",
+ name: "XP",
+ description: <>The amount of experience to give the player>,
+ type: "input",
+ isNumber: true,
+ optional: false,
+ },
+ {
+ key: "level",
+ name: "Should give levels?",
+ description: <>Whether to give the player levels instead of points>,
+ type: "boolean",
+ optional: true,
+ },
+ ],
+ },
+ {
+ type: "questlog:loot_table",
+ description: <>Gives the player loot from a loot table>,
+ additional: [
+ {
+ key: "loot_table",
+ name: "Loot Table",
+ description: <>The loot table to give the player>,
+ type: "input",
+ optional: false,
+ autocomplete: LOOT_TABLES,
+ },
+ ],
+ },
+];
diff --git a/public/script/questlog/field.tsx b/public/script/questlog/field.tsx
index 4072436..7e62149 100644
--- a/public/script/questlog/field.tsx
+++ b/public/script/questlog/field.tsx
@@ -3,6 +3,111 @@ import { _createElement } from "simple-jsx-handler";
declare const React: JSX.IntrinsicElements;
import { TypeDefinitionAdditional } from "./types";
+import { OBJECTIVE_TYPES } from "./definitions";
+
+function createObjectiveEditor(value: any, onChange: (newValue: any) => void): HTMLElement {
+ let currentData = value || { type: "questlog:block_mine" };
+
+ const fieldsContainer =
true, the stat's value will be tracked since the creation of the quest.
- false, the stat's value will be the player's total stat value.
- >
- ),
- },
- ],
- },
- {
- type: "questlog:quest_complete",
- description: <>Tracks this quest to be completed, useful for adding dependency quests.>,
- additional: [
- {
- key: "quest",
- name: "Quest",
- description: <>The quest to track>,
- type: "input",
- optional: false,
- },
- ],
- },
- {
- type: "questlog:block_mine",
- description: <>Tracks the number of blocks mined by the player>,
- additional: [
- {
- key: "block",
- name: "Block",
- description: (
- <>
- The block to track.
- #.
- >
- ),
- type: "input",
- optional: false,
- autocomplete: BLOCKS_TAGS,
- },
- ],
- },
- {
- type: "questlog:block_place",
- description: <>Tracks the number of blocks placed by the player>,
- additional: [
- {
- key: "block",
- name: "Block",
- description: (
- <>
- The block to track.
- #.
- >
- ),
- type: "input",
- optional: false,
- autocomplete: BLOCKS_TAGS,
- },
- ],
- },
- {
- type: "questlog:entity_approach",
- description: <>Tracks the number of times the player approaches a specific entity>,
- additional: [
- {
- key: "entity",
- name: "Entity",
- description: <>The entity to track.>,
- type: "input",
- optional: false,
- autocomplete: ENTITIES,
- },
- {
- key: "range",
- name: "Range",
- description: <>The range to track the entity in>,
- type: "input",
- isNumber: true,
- optional: false,
- },
- ],
- },
- {
- type: "questlog:entity_breed",
- description: <>Tracks the number of times the player breeds entities>,
- additional: [
- {
- key: "entity",
- name: "Entity",
- description: <>The entity to track.>,
- type: "input",
- optional: false,
- autocomplete: ENTITIES,
- },
- ],
- },
- {
- type: "questlog:entity_death",
- description: <>Tracks the number of times the player dies to a specific entity>,
- additional: [
- {
- key: "entity",
- name: "Entity",
- description: <>The entity to track.>,
- type: "input",
- optional: false,
- autocomplete: ENTITIES,
- },
- ],
- },
- {
- type: "questlog:entity_kill",
- description: <>Tracks the number of a specific export type of entity the player kills>,
- additional: [
- {
- key: "entity",
- name: "Entity",
- description: <>The entity to track.>,
- type: "input",
- optional: false,
- autocomplete: ENTITIES,
- },
- ],
- },
- {
- type: "questlog:item_craft",
- description: <>Tracks the number of a specific item the player crafts>,
- additional: [
- {
- key: "item",
- name: "Item",
- description: (
- <>
- The item to track.
- #.
- >
- ),
- type: "input",
- optional: false,
- autocomplete: ITEMS_TAGS,
- },
- ],
- },
- {
- type: "questlog:item_drop",
- description: <>Tracks the number of a specific item the player drops>,
- additional: [
- {
- key: "item",
- name: "Item",
- description: (
- <>
- The item to track.
- #.
- >
- ),
- type: "input",
- optional: false,
- autocomplete: ITEMS_TAGS,
- },
- ],
- },
- {
- type: "questlog:item_equip",
- description: <>Tracks the number of times the player equips a specific item>,
- additional: [
- {
- key: "item",
- name: "Item",
- description: (
- <>
- The item to track.
- #.
- >
- ),
- type: "input",
- optional: false,
- autocomplete: ITEMS_TAGS,
- },
- {
- key: "slot",
- name: "Slot",
- description: <>The slot to track.>,
- type: "select",
- optional: false,
- options: ["mainhand", "offhand", "feet", "legs", "chest", "head"],
- },
- ],
- },
- {
- type: "questlog:item_obtain",
- description: <>Tracks the number of a specific item the player has in their inventory>,
- additional: [
- {
- key: "item",
- name: "Item",
- description: (
- <>
- The item to track.
- #.
- >
- ),
- type: "input",
- optional: false,
- autocomplete: ITEMS_TAGS,
- },
- ],
- },
- {
- type: "questlog:item_pickup",
- description: <>Tracks the number of a specific item the player picks up>,
- additional: [
- {
- key: "item",
- name: "Item",
- description: (
- <>
- The item to track.
- #.
- >
- ),
- type: "input",
- optional: false,
- autocomplete: ITEMS_TAGS,
- },
- ],
- },
- {
- type: "questlog:item_use",
- description: <>Tracks the number of times the player uses a specific item>,
- additional: [
- {
- key: "item",
- name: "Item",
- description: (
- <>
- The item to track.
- #.
- >
- ),
- type: "input",
- optional: false,
- autocomplete: ITEMS_TAGS,
- },
- ],
- },
- {
- type: "questlog:visit_biome",
- description: <>Tracks the number of times the player visits a specific biome>,
- additional: [
- {
- key: "biome",
- name: "Biome",
- description: <>The biome to track.>,
- type: "input",
- optional: false,
- autocomplete: BIOMES,
- },
- ],
- },
- {
- type: "questlog:visit_dimension",
- description: <>Tracks the number of times the player visits a specific dimension>,
- additional: [
- {
- key: "dimension",
- name: "Dimension",
- description: <>The dimension to track.>,
- type: "input",
- optional: false,
- autocomplete: DIMENSIONS,
- },
- ],
- },
- {
- type: "questlog:trample",
- description: <>Tracks the number of times the player tramples farmland>,
- },
- {
- type: "questlog:effect_added",
- description: <>Tracks the number of times the player gains a specific effect>,
- additional: [
- {
- key: "effect",
- name: "Effect",
- description: <>The effect to track.>,
- type: "input",
- optional: false,
- autocomplete: EFFECTS,
- },
- ],
- },
- {
- type: "questlog:enchant",
- description: <>Tracks the number of times the player enchants an item with a specific enchantment>,
- additional: [
- {
- key: "enchantment",
- name: "Enchantment",
- description: (
- <>
- The enchantment to track.
-