aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/App.vue12
-rw-r--r--src/assets/base.css230
-rw-r--r--src/assets/main.css2
-rw-r--r--src/assets/quests-logo.pngbin54415 -> 0 bytes
-rw-r--r--src/components/Control/Button.vue82
-rw-r--r--src/components/Control/Checkbox.vue42
-rw-r--r--src/components/Control/ItemStackForm.vue50
-rw-r--r--src/components/Control/ItemStackModal.vue172
-rw-r--r--src/components/Control/ItemStackPicker.vue100
-rw-r--r--src/components/Control/Modal.vue68
-rw-r--r--src/components/Control/TrueFalseSwitch.vue54
-rw-r--r--src/components/Editor/Category/CategoryChildrenOptionsPanel.vue53
-rw-r--r--src/components/Editor/Category/CategoryOptionsPanel.vue54
-rw-r--r--src/components/Editor/EditorOptionsPanel.vue18
-rw-r--r--src/components/Editor/EditorPane.vue216
-rw-r--r--src/components/Editor/EditorSidebar.vue28
-rw-r--r--src/components/Editor/EditorSidebarCategory.vue94
-rw-r--r--src/components/Editor/EditorSidebarQuest.vue68
-rw-r--r--src/components/Editor/Quest/Modal/DeleteQuestModal.vue42
-rw-r--r--src/components/Editor/Quest/Modal/DuplicateQuestModal.vue69
-rw-r--r--src/components/Editor/Quest/Modal/RenameQuestModal.vue69
-rw-r--r--src/components/Editor/Quest/QuestOptionsPanel.vue145
-rw-r--r--src/components/Editor/Quest/QuestTasksOptionsPanel.vue98
-rw-r--r--src/components/Editor/Quest/Task/Modal/AddTaskModal.vue90
-rw-r--r--src/components/Editor/Quest/Task/Modal/ChangeTaskModal.vue77
-rw-r--r--src/components/Editor/Quest/Task/TaskConfiguration.vue209
-rw-r--r--src/components/Editor/Quest/Task/TaskConfigurationRow.vue195
-rw-r--r--src/components/Header/SiteHeader.vue43
-rw-r--r--src/data/materials.json1924
-rw-r--r--src/data/taskDefinitions.json137
-rw-r--r--src/data/testData.json384
-rw-r--r--src/lib/materials.ts3
-rw-r--r--src/lib/questsLoader.ts68
-rw-r--r--src/lib/util.ts18
-rw-r--r--src/main.ts40
-rw-r--r--src/router/index.ts23
-rw-r--r--src/stores/session.ts171
-rw-r--r--src/views/EditorView.vue37
38 files changed, 0 insertions, 5185 deletions
diff --git a/src/App.vue b/src/App.vue
deleted file mode 100644
index 0b4985d..0000000
--- a/src/App.vue
+++ /dev/null
@@ -1,12 +0,0 @@
-<script setup lang="ts">
-import SiteHeader from '@/components/Header/SiteHeader.vue';
-</script>
-
-<template>
- <SiteHeader />
-
- <RouterView />
-</template>
-
-<style scoped>
-</style>
diff --git a/src/assets/base.css b/src/assets/base.css
deleted file mode 100644
index 5e116e8..0000000
--- a/src/assets/base.css
+++ /dev/null
@@ -1,230 +0,0 @@
-/* color palette from <https://github.com/vuejs/theme> */
-:root {
- --c-white: #ffffff;
- --c-white-soft: #f8f8f8;
- --c-white-mute: #f2f2f2;
-
- --c-black: #181818;
- --c-black-soft: #222222;
- --c-black-mute: #282828;
-
- --c-indigo: #2c3e50;
-
- --c-divider-light-1: rgba(60, 60, 60, 0.2);
- --c-divider-light-2: rgba(60, 60, 60, 0.4);
- --c-divider-dark-1: rgba(84, 84, 84, 0.2);
- --c-divider-dark-2: rgba(84, 84, 84, 0.4);
-
- --c-text-light-1: #f8f8f8;
- --c-text-light-2: #a7a7a7;
- --c-text-dark-1: #181818;
- --c-text-dark-2: #222222;
-
- --c-brand: #8b72f0;
- --c-brand-light: #a08df5;
- --c-brand-dark: #7058d1;
- --c-brand-mute: #866ee755;
- --c-brand-highlight: #9885e463;
-
- --c-true: #2ecc71;
- --c-false: #e74c3c;
-}
-
-/* semantic color variables for this project */
-:root {
- --color-background: var(--c-white);
- --color-background-soft: var(--c-white-soft);
- --color-background-mute: var(--c-white-mute);
-
- --color-border: var(--c-divider-light-2);
- --color-border-soft: var(--c-divider-light-1);
-
- --color-heading: var(--c-text-dark-1);
- --color-text: var(--c-text-dark-1);
- --color-text-mute: var(--c-text-dark-2);
- --color-text-primary: var(--c-brand-dark);
-
- --color-primary: var(--c-brand);
- --color-primary-light: var(--c-brand-light);
- --color-primary-dark: var(--c-brand-dark);
- --color-primary-mute: var(--c-brand-mute);
-
- --color-hover: var(--c-brand-highlight);
-
- --color-true: var(--c-true);
- --color-false: var(--c-false);
-
- --section-gap: 160px;
-}
-
-@media (prefers-color-scheme: dark) {
- :root {
- --color-background: var(--c-black);
- --color-background-soft: var(--c-black-soft);
- --color-background-mute: var(--c-black-mute);
-
- --color-border: var(--c-divider-dark-2);
- --color-border-soft: var(--c-divider-dark-1);
-
- --color-heading: var(--c-text-light-1);
- --color-text: var(--c-text-light-1);
- --color-text-mute: var(--c-text-light-2);
- --color-text-primary: var(--c-brand-light);
- }
-}
-
-*,
-*::before,
-*::after {
- box-sizing: border-box;
- margin: 0;
- font-weight: normal;
-}
-
-body {
- min-height: 100vh;
- color: var(--color-text);
- background: var(--color-background);
- transition:
- color 0.5s,
- background-color 0.5s;
- line-height: 1.6;
- font-family:
- Inter,
- -apple-system,
- BlinkMacSystemFont,
- 'Segoe UI',
- Roboto,
- Oxygen,
- Ubuntu,
- Cantarell,
- 'Fira Sans',
- 'Droid Sans',
- 'Helvetica Neue',
- sans-serif;
- font-size: 15px;
- text-rendering: optimizeLegibility;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-code {
- font-family: 'Fira Code', monospace;
-}
-
-input {
- font-family: inherit;
- font-size: inherit;
- color: inherit;
- background: var(--color-background-soft);
- border: 1px solid var(--color-border);
- padding: 0.5em 1em;
- border-radius: 4px;
- transition: border-color 0.5s;
-}
-
-input:focus {
- outline: none;
- border-color: var(--color-primary);
-}
-
-input:disabled {
- background: var(--color-background-mute);
- border-color: var(--color-border);
- color: var(--color-text-mute);
- cursor: not-allowed;
-}
-
-fieldset {
- border: 1px solid var(--color-border);
-}
-
-input[type="checkbox"] {
- accent-color: var(--color-primary);
-}
-
-input[type="radio"] {
- accent-color: var(--color-primary);
-}
-
-.multiselect__input {
- background: var(--color-background-soft) !important ;
- color: inherit !important;
-
- &::placeholder {
- color: rgba(255, 255, 255, .2) !important;
- }
-}
-
-.multiselect__tags {
- background: var(--color-background-soft) !important;
- border: 1px solid var(--color-border) !important;
- border-radius: 4px !important;
- overflow-y: auto !important;
-}
-
-.multiselect__single {
- font-family: monospace !important;
- background: var(--color-background-soft) !important;
- color: var(--color-text) !important;
- font-size: 0.8rem !important;
-}
-
-.multiselect__content {
- font-family: monospace;
-
- &-wrapper {
- background: var(--color-background);
- border: 0;
- border-top-left-radius: 2px;
- border-top-right-radius: 2px;
- box-shadow: 0 -1rem 2rem rgba(0, 0, 0, .1);
- }
-}
-
-.multiselect__element {
- &:not(:first-child) {
- border-top: 1px solid rgba(0, 0, 0, .2);
- }
-}
-
-.multiselect__option {
- &--highlight {
- background: rgba(255, 255, 255, .2);
-
- &:after {
- background: rgba(0, 0, 0, .2);
- }
- }
-
- &--selected {
- background: var(--color-primary);
- color: white;
-
- &:after {
- color: rgba(0, 0, 0, .5);
- }
-
- }
-}
-
-.control-group {
- display: flex;
- flex-direction: row;
- gap: 1rem;
-}
-
-.option-group {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-
- label {
- font-weight: 700;
- }
-}
-
-.error-text {
- color: var(--color-false);
- font-size: 0.8rem;
-} \ No newline at end of file
diff --git a/src/assets/main.css b/src/assets/main.css
deleted file mode 100644
index 37a2a09..0000000
--- a/src/assets/main.css
+++ /dev/null
@@ -1,2 +0,0 @@
-@import 'vue-multiselect/dist/vue-multiselect.css';
-@import './base.css'; \ No newline at end of file
diff --git a/src/assets/quests-logo.png b/src/assets/quests-logo.png
deleted file mode 100644
index 0d0194f..0000000
--- a/src/assets/quests-logo.png
+++ /dev/null
Binary files differ
diff --git a/src/components/Control/Button.vue b/src/components/Control/Button.vue
deleted file mode 100644
index efd91c2..0000000
--- a/src/components/Control/Button.vue
+++ /dev/null
@@ -1,82 +0,0 @@
-<script setup lang="ts">
-const props = defineProps({
- type: {
- type: String,
- required: false,
- default: 'text',
- },
- label: String,
- icon: Array<String>,
- disabled: Boolean,
-});
-
-const emit = defineEmits(['click']);
-
-const onClick = (event: MouseEvent) => {
- if (!props.disabled) {
- emit('click', event);
- }
-};
-</script>
-
-<template>
- <a id="button" :class="{text: type === 'text', solid: type === 'solid', disabled: disabled}" @click.stop="onClick">
- <font-awesome-icon :icon="icon" />
- {{ label }}
- </a>
-</template>
-
-<style scoped>
-#button {
- display: flex;
- align-items: center;
- gap: 0.25rem;
- user-select: none;
-}
-
-.text {
- background-color: transparent;
- color: var(--color-text-primary);
- transition: color 0.3s;
- font-weight: 700;
- cursor: pointer;
-
- &.disabled {
- color: var(--color-text-mute);
- cursor: not-allowed;
- }
-
- &:hover {
- color: var(--color-primary-dark);
- }
-
- &.disabled:hover {
- color: var(--color-text-mute);
- }
-}
-
-.solid {
- background-color: var(--color-primary);
- transition: background-color 0.3s;
- color: var(--color-text);
- padding: 0.25rem 0.5rem;
- border-radius: 4px;
- font-weight: 700;
- cursor: pointer;
-
- &.disabled {
- background-color: var(--color-border);
- color: var(--color-text-mute);
- cursor: not-allowed;
- }
-
- &:hover {
- background-color: var(--color-primary-dark);
- }
-
- &.disabled:hover {
- background-color: var(--color-border);
- }
-}
-
-</style> \ No newline at end of file
diff --git a/src/components/Control/Checkbox.vue b/src/components/Control/Checkbox.vue
deleted file mode 100644
index e0325e7..0000000
--- a/src/components/Control/Checkbox.vue
+++ /dev/null
@@ -1,42 +0,0 @@
-<script setup lang="ts">
-const model = defineModel();
-
-defineProps({
- id: String,
- label: String,
- description: String,
-});
-
-</script>
-
-<template>
- <div class="checkbox">
- <label id="wrapper" :for="id">
- <input :id="id" type="checkbox" v-model="model" />
- <span id="label">{{ label }}</span>
- <span id="description">{{ description }}</span>
- </label>
- </div>
-</template>
-
-<style scoped>
-#label {
- display: block;
- font-weight: bold;
-}
-
-#description {
- display: block;
- font-size: 0.8em;
-}
-
-input {
- float: left;
- margin: 5px 0 0 -20px;
-}
-
-.checkbox {
- padding: 0 0 0 20px;
-}
-
-</style> \ No newline at end of file
diff --git a/src/components/Control/ItemStackForm.vue b/src/components/Control/ItemStackForm.vue
deleted file mode 100644
index 250e8c9..0000000
--- a/src/components/Control/ItemStackForm.vue
+++ /dev/null
@@ -1,50 +0,0 @@
-<script setup lang="ts">
-import { computed } from 'vue';
-import materials from '@/lib/materials';
-
-const model = defineModel<any>();
-
-if (typeof model.value !== 'object' || model.value === null) {
- model.value = {};
-}
-
-const itemName = computed({
- get() {
- return model.value.name;
- },
- set(newValue: string) {
- model.value.name = newValue;
- },
-});
-
-const itemType = computed({
- get() {
- return model.value.type || model.value.material || model.value.item;
- },
- set(newValue: string) {
- if (model.value.material) {
- model.value.material = newValue;
- } else if (model.value.item) {
- model.value.item = newValue;
- } else {
- model.value.type = newValue;
- }
- },
-});
-</script>
-
-<template>
- <div class="option-group">
- <label for="itemstack-name">Name</label>
- <input id="itemstack-name" name="itemstack-name" v-model="itemName" placeholder="Enter a display name" />
- </div>
-
- <div class="option-group">
- <label for="itemstack-name">Type</label>
- <multiselect v-model="itemType"
- :options="materials" :searchable="true" placeholder="Choose a material" />
- </div>
-</template>
-
-<style scoped>
-</style> \ No newline at end of file
diff --git a/src/components/Control/ItemStackModal.vue b/src/components/Control/ItemStackModal.vue
deleted file mode 100644
index 642c5f9..0000000
--- a/src/components/Control/ItemStackModal.vue
+++ /dev/null
@@ -1,172 +0,0 @@
-<script setup lang="ts">
-import Modal from '@/components/Control/Modal.vue';
-import Button from '@/components/Control/Button.vue';
-import { computed, ref } from 'vue';
-import materials from '@/lib/materials';
-import ItemStackForm from './ItemStackForm.vue';
-
-const model = defineModel();
-
-const emit = defineEmits(['confirm']);
-
-const props = defineProps({
- value: String,
-});
-
-//TODO unshitify
-const value = ref<any>(props.value);
-
-const isQuestItem = computed(() => {
- return value.value?.['quest-item'] !== undefined;
-});
-const isItemStack = computed(() => {
- return (
- typeof value.value === 'object'
- && (
- value.value?.item !== undefined
- || value.value?.type !== undefined
- || value.value?.material !== undefined
- ))
-});
-const isMaterial = computed(() => {
- return typeof value.value === 'string' && materials.includes(value.value)
-});
-
-const selectedType = ref(
- isQuestItem.value
- ? 'questitem'
- : isItemStack.value
- ? 'itemstack'
- : isMaterial.value
- ? 'material'
- : ''
-);
-
-const noTypeSelected = computed(() => selectedType.value === '');
-const noValue = computed(() => !isQuestItem.value && !isItemStack.value && !isMaterial.value);
-
-const setSelectedType = (type: string) => {
- if (type === 'questitem') {
- value.value = {};
- } else if (type === 'itemstack') {
- value.value = {};
- } else if (type === 'material') {
- value.value = '';
- }
- selectedType.value = type;
-};
-
-const confirm = () => {
- emit('confirm', value.value);
-};
-</script>
-
-<template>
- <Modal v-model="model">
- <template v-slot:header>
- <h2>Edit ItemStack</h2>
- </template>
-
- <template v-slot:body>
- <div id="type">
- <span class="option" @click="setSelectedType('questitem')" :class="{selected: selectedType === 'questitem'}">
- <span>
- <font-awesome-icon :icon="['fas', 'fa-tag']" />
- Quest Item
- </span>
- <p v-if="noTypeSelected">Re-use a quest item.</p>
- </span>
- <span class="option" @click="setSelectedType('itemstack')" :class="{selected: selectedType === 'itemstack'}">
- <span>
- <font-awesome-icon :icon="['fas', 'fa-cube']" />
- ItemStack
- </span>
- <p v-if="noTypeSelected">Define a new item stack.</p>
- </span>
- <span class="option" @click="setSelectedType('material')" :class="{selected: selectedType === 'material'}">
- <span>
- <font-awesome-icon :icon="['fas', 'fa-apple-whole']" />
- Material
- </span>
- <p v-if="noTypeSelected">Define a specific item type.</p>
- </span>
- </div>
-
- <div id="material" class="option-group" v-if="selectedType === 'material'">
- <label for="material">Material</label>
- <multiselect v-model="value"
- :options="materials" :searchable="true" placeholder="Enter material name" />
- </div>
-
- <div id="itemstack" class="option-group" v-if="selectedType === 'itemstack'">
- <ItemStackForm v-model="value" />
- </div>
-
-
- <div id="confirm" class="control-group">
- <Button
- :icon="['fas', 'fa-times']"
- :label="'Cancel'"
- @click="model = false"
- ></Button>
- <Button
- type="solid"
- :icon="['fas', 'fa-check']"
- :label="'Confirm'"
- @click="confirm"
- ></Button>
- <!-- :disabled="noTypeSelected || noValue" -->
- </div>
- </template>
- </Modal>
-</template>
-
-<style scoped>
-#confirm {
- display: flex;
- justify-content: flex-end;
- margin-top: 1rem;
-}
-
-#type {
- display: flex;
- justify-content: space-around;
- gap: 0.25rem;
- user-select: none;
- margin-bottom: 1rem;
-
- .option {
- border: 1px solid var(--color-border);
- cursor: pointer;
- display: flex;
- flex-direction: column;
- flex-basis: 0;
- flex-grow: 1;
- align-items: center;
- gap: 0.5rem;
- padding: 0.5rem;
- background-color: var(--color-background-soft);
- transition: background-color 0.3s;
-
- span {
- display: flex;
- align-items: center;
- gap: 0.5rem;
- font-weight: 700;
- }
-
- p {
- text-align: center;
- font-size: 0.8rem;
- }
-
- &:hover {
- background-color: var(--color-hover);
- }
-
- &.selected {
- background-color: var(--color-primary-mute);
- }
- }
-}
-</style> \ No newline at end of file
diff --git a/src/components/Control/ItemStackPicker.vue b/src/components/Control/ItemStackPicker.vue
deleted file mode 100644
index d16090e..0000000
--- a/src/components/Control/ItemStackPicker.vue
+++ /dev/null
@@ -1,100 +0,0 @@
-<script setup lang="ts">
-import { computed, ref } from 'vue';
-import ItemStackModal from './ItemStackModal.vue';
-import materials from '@/lib/materials';
-
-const props = defineProps<{
- value: any;
-}>();
-const emit = defineEmits(['update']);
-
-const value = ref(props.value);
-
-const showItemStackModal = ref(false);
-
-//TODO unshitify
-const empty = computed(() => {
- return value.value === undefined
- || value.value === null
- || value.value === ''
- || (Array.isArray(value.value) && value.value.length === 0)
- || (typeof value.value === 'object' && Object.keys(value.value).length === 0);
-});
-const isQuestItem = computed(() => {
- return value.value?.['quest-item'] !== undefined;
-});
-const isItemStack = computed(() => {
- if (typeof value.value !== 'object' || value.value === null) {
- return false;
- }
-
- const key = 'item' in value.value
- ? 'item'
- : 'type' in value.value
- ? 'type'
- : 'material'
-
- return (!!value.value[key]);
-});
-const isMaterial = computed(() => {
- return typeof value.value === 'string' && materials.includes(value.value)
-});
-
-const update = (newValue: any) => {
- value.value = newValue;
- showItemStackModal.value = false;
- emit('update', value.value);
-};
-</script>
-
-<template>
- <div class="itemstack" @click="showItemStackModal = true">
- <span v-if="empty" class="empty">ItemStack...</span>
- <span v-if="isQuestItem" class="item"><font-awesome-icon :icon="['fas', 'fa-tag']" /> Quest Item</span>
- <span v-if="isItemStack" class="item"><font-awesome-icon :icon="['fas', 'fa-cube']" /> ItemStack of '{{ value.type || value.item || value.material }}'</span>
- <span v-if="isMaterial" class="item"><font-awesome-icon :icon="['fas', 'fa-apple-whole']" /> {{ value }}</span>
- <span v-if="!empty && !isQuestItem && !isItemStack && !isMaterial" class="invalid"><font-awesome-icon :icon="['fas', 'fa-triangle-exclamation']" /> Invalid ItemStack</span>
- </div>
-
- <ItemStackModal
- v-model="showItemStackModal"
- :value="value"
- @confirm="update"
- />
-</template>
-
-<style scoped>
-.itemstack {
- display: flex;
- width: 100%;
- height: 100%;
- cursor: pointer;
- align-items: center;
- padding: 0.5rem;
- user-select: none;
- transition: background-color 0.3s;
- background-color: var(--color-background-soft);
-
- span {
- font-family: monospace;
- font-size: 0.8rem;
- }
-
- .empty {
- color: var(--color-text-mute);
- }
-
- .item {
- color: var(--color-primary);
- }
-
- .invalid {
- color: var(--color-false);
- }
-
- &:hover {
- background-color: var(--color-hover);
- }
-}
-
-</style> \ No newline at end of file
diff --git a/src/components/Control/Modal.vue b/src/components/Control/Modal.vue
deleted file mode 100644
index 46d5da5..0000000
--- a/src/components/Control/Modal.vue
+++ /dev/null
@@ -1,68 +0,0 @@
-<script setup lang="ts">
-const model = defineModel();
-
-</script>
-
-<template>
- <div id="modal" class="modal" :class="{ 'is-active': model }">
- <div class="modal-background" @click="model = false"></div>
- <div class="modal-content">
- <div class="header" v-if="$slots.header">
- <slot name="header" />
- </div>
- <slot name="body" />
- <slot />
- </div>
- </div>
-</template>
-
-<style scoped>
-#modal {
- align-items: center;
- justify-content: center;
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- z-index: 1000;
- background-color: rgba(0, 0, 0, 0.5);
- transition: opacity 0.3s;
- display: none;
- overflow: visible;
-}
-
-.modal-content {
- background-color: var(--color-background);
- border: 1px solid var(--color-border);
- padding: 1rem;
- width: 100%;
- max-width: 600px;
- max-height: 80%;
- overflow-y: visible;
- border-radius: 4px;
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
-}
-
-.modal-background {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background-color: rgba(0, 0, 0, 0.5);
- z-index: -1;
-}
-
-.is-active {
- opacity: 1 !important;
- pointer-events: all !important;
- display: flex !important;
-}
-
-.header {
- border-bottom: 1px solid var(--color-border);
- margin-bottom: 1rem;
-}
-
-</style> \ No newline at end of file
diff --git a/src/components/Control/TrueFalseSwitch.vue b/src/components/Control/TrueFalseSwitch.vue
deleted file mode 100644
index a0a3392..0000000
--- a/src/components/Control/TrueFalseSwitch.vue
+++ /dev/null
@@ -1,54 +0,0 @@
-<script setup lang="ts">
-import { ref } from 'vue';
-
-const props = defineProps<{
- value: boolean;
-}>();
-const emit = defineEmits(['update']);
-
-const value = ref(props.value);
-
-const invert = () => {
- value.value = !value.value;
- emit('update', value.value);
-};
-</script>
-
-<template>
- <div class="switch" @click="invert">
- <span v-if="value" class="true"><font-awesome-icon :icon="['fas', 'fa-check']" /> True</span>
- <span v-else class="false"><font-awesome-icon :icon="['fas', 'fa-xmark']" /> False</span>
- </div>
-</template>
-
-<style scoped>
-.switch {
- display: flex;
- width: 100%;
- height: 100%;
- cursor: pointer;
- align-items: center;
- padding: 0.5rem;
- user-select: none;
- transition: background-color 0.3s;
- background-color: var(--color-background-soft);
-
- span {
- font-family: monospace;
- font-size: 0.8rem;
- }
-
- .true {
- color: var(--color-text-primary);
- }
-
- .false {
- color: var(--color-false);
- }
-
- &:hover {
- background-color: var(--color-hover);
- }
-}
-
-</style> \ No newline at end of file
diff --git a/src/components/Editor/Category/CategoryChildrenOptionsPanel.vue b/src/components/Editor/Category/CategoryChildrenOptionsPanel.vue
deleted file mode 100644
index 6e96f64..0000000
--- a/src/components/Editor/Category/CategoryChildrenOptionsPanel.vue
+++ /dev/null
@@ -1,53 +0,0 @@
-<script setup lang="ts">
-import { useSessionStore, type EditorCategory } from '@/stores/session';
-import { computed } from 'vue';
-import EditorOptionsPanel from '../EditorOptionsPanel.vue';
-
-const props = defineProps<{
- categoryId: string;
-}>();
-
-const sessionStore = useSessionStore();
-
-const category = computed(() => {
- return sessionStore.getCategoryById(props.categoryId) as EditorCategory;
-});
-</script>
-
-<template>
- <EditorOptionsPanel v-if="category">
- <div id="options">
- <h2>Quests in this category</h2>
- <p>Drag to reorder.</p>
- <div class="option-group">
- </div>
- </div>
- </EditorOptionsPanel>
-</template>
-
-<style>
-#options {
- display: flex;
- flex-direction: column;
- gap: 1rem;
-}
-
-.option-group {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-}
-
-.description {
- font-size: 0.8em;
-}
-
-label {
- font-weight: 700;
-}
-
-h2 {
- border-bottom: 1px solid var(--color-border);
-}
-</style>
-
diff --git a/src/components/Editor/Category/CategoryOptionsPanel.vue b/src/components/Editor/Category/CategoryOptionsPanel.vue
deleted file mode 100644
index f7d548c..0000000
--- a/src/components/Editor/Category/CategoryOptionsPanel.vue
+++ /dev/null
@@ -1,54 +0,0 @@
-<script setup lang="ts">
-import { useSessionStore, type EditorCategory } from '@/stores/session';
-import { computed } from 'vue';
-import EditorOptionsPanel from '../EditorOptionsPanel.vue';
-import Checkbox from '@/components/Control/Checkbox.vue';
-
-const props = defineProps<{
- categoryId: string;
-}>();
-
-const sessionStore = useSessionStore();
-
-const category = computed(() => {
- return sessionStore.getCategoryById(props.categoryId) as EditorCategory;
-});
-</script>
-
-<template>
- <EditorOptionsPanel v-if="category">
- <div id="options">
- <div class="option-group">
- <Checkbox id="category-permissionrequired" label="Require permission for category"
- description="Players must have permission to open and start quests in this category." v-model="category.permissionRequired" />
- </div>
- </div>
- </EditorOptionsPanel>
-</template>
-
-<style>
-#options {
- display: flex;
- flex-direction: column;
- gap: 1rem;
-}
-
-.option-group {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-}
-
-.description {
- font-size: 0.8em;
-}
-
-label {
- font-weight: 700;
-}
-
-h2 {
- border-bottom: 1px solid var(--color-border);
-}
-</style>
-
diff --git a/src/components/Editor/EditorOptionsPanel.vue b/src/components/Editor/EditorOptionsPanel.vue
deleted file mode 100644
index 1415d84..0000000
--- a/src/components/Editor/EditorOptionsPanel.vue
+++ /dev/null
@@ -1,18 +0,0 @@
-<script setup lang="ts">
-</script>
-
-<template>
- <div id="options-panel">
- <slot />
- </div>
-</template>
-
-<style scoped>
-#options-panel {
- width: 100%;
- background-color: var(--color-background);
- border: 1px solid var(--color-border);
- padding: 1rem;
- height: 100%;
-}
-</style> \ No newline at end of file
diff --git a/src/components/Editor/EditorPane.vue b/src/components/Editor/EditorPane.vue
deleted file mode 100644
index bf9532a..0000000
--- a/src/components/Editor/EditorPane.vue
+++ /dev/null
@@ -1,216 +0,0 @@
-<script setup lang="ts">
-import { useSessionStore } from '@/stores/session';
-import { computed, ref } from 'vue';
-import { stripColorCodes } from '@/lib/util';
-import QuestOptionsPanel from '@/components/Editor/Quest/QuestOptionsPanel.vue';
-import QuestTasksOptionsPanel from '@/components/Editor/Quest/QuestTasksOptionsPanel.vue';
-import CategoryOptionsPanel from '@/components/Editor/Category/CategoryOptionsPanel.vue';
-import CategoryChildrenOptionsPanel from '@/components/Editor/Category/CategoryChildrenOptionsPanel.vue';
-import Button from '@/components/Control/Button.vue';
-import DeleteQuestModal from '@/components/Editor/Quest/Modal/DeleteQuestModal.vue';
-import RenameQuestModal from '@/components/Editor/Quest/Modal/RenameQuestModal.vue';
-import DuplicateQuestModal from '@/components/Editor/Quest/Modal/DuplicateQuestModal.vue';
-
-const sessionStore = useSessionStore();
-
-const selectedType = computed(() => sessionStore.editor.selected.type);
-const selectedId = computed(() => sessionStore.editor.selected.id);
-
-const selectedName = computed(() => {
- if (selectedType.value === 'Quest' && selectedId.value) {
- return sessionStore.getQuestById(selectedId.value)?.display.name;
- } else if (selectedType.value === 'Category' && selectedId.value) {
- return sessionStore.getCategoryById(selectedId.value)?.display.name;
- } else {
- return '';
- }
-});
-
-const categoryFromSelectedQuest = computed(() => {
- if (!selectedId.value || selectedType.value !== 'Quest') return null;
-
- const quest = sessionStore.getQuestById(selectedId.value);
- if (quest) {
- return sessionStore.getCategoryById(quest.options.category) || null;
- } else {
- return null;
- }
-});
-
-const showDeleteModal = ref(false);
-const showRenameModal = ref(false);
-const showDuplicateModal = ref(false);
-
-const renameQuest = (oldId: string, newId: string) => {
- sessionStore.changeQuestId(oldId, newId);
- sessionStore.editor.selected.id = newId;
- showRenameModal.value = false;
-};
-
-const deleteQuest = (questId: string) => {
- sessionStore.deleteQuest(questId);
- sessionStore.setEditorSelected(null, null);
- showDeleteModal.value = false;
-};
-
-const duplicateQuest = (oldId: string, newId: string) => {
- sessionStore.duplicateQuest(oldId, newId);
- sessionStore.editor.selected.id = newId;
- showDuplicateModal.value = false;
-};
-</script>
-
-<template>
- <div id="pane-container" v-if="!selectedId || !selectedType">
- <h1 class="none-selected">Select a quest or category from the sidebar to continue</h1>
- </div>
- <div id="pane-container" v-if="selectedId && selectedType">
- <div id="header">
- <span id="path">
- <template v-if="selectedType === 'Quest'">
- <template v-if="categoryFromSelectedQuest">
- <font-awesome-icon class="icon" :icon="['fas', 'fa-folder']"/>
- {{ stripColorCodes(categoryFromSelectedQuest?.display.name) }}
- <font-awesome-icon class="chevron" :icon="['fas', 'fa-chevron-right']"/>
- </template>
- <font-awesome-icon class="icon" :icon="['far', 'fa-compass']"/>
- <span class="title">{{ stripColorCodes(selectedName!) }} </span>
- <code>({{ selectedId }})</code>
- </template>
- <template v-if="selectedType === 'Category'">
- <font-awesome-icon class="icon" :icon="['fas', 'fa-folder']"/>
- <span class="title">{{ stripColorCodes(selectedName!) }} </span>
- <code>({{ selectedId }})</code>
- </template>
- </span>
- <span id="controls" class="control-group">
- <Button
- v-if="selectedType === 'Quest'"
- :icon="['fas', 'fa-code']"
- :label="'YAML'"
- ></Button>
- <Button
- v-if="selectedType === 'Quest'"
- :icon="['fas', 'fa-copy']"
- :label="'Duplicate'"
- @click="showDuplicateModal = true"
- ></Button>
- <Button
- :icon="['fas', 'fa-pen']"
- :label="'Rename'"
- @click="showRenameModal = true"
- ></Button>
- <Button
- :icon="['fas', 'fa-trash']"
- :label="'Delete'"
- @click="showDeleteModal = true"
- ></Button>
- <Button
- type="solid"
- :disabled="true"
- :icon="['fas', 'fa-save']"
- :label="'Save'"
- ></Button>
- </span>
- </div>
-
- <div id="options-container">
- <QuestOptionsPanel v-if="selectedType === 'Quest'" :questId="selectedId" />
- <QuestTasksOptionsPanel v-if="selectedType === 'Quest'" :questId="selectedId" />
-
- <CategoryOptionsPanel v-if="selectedType === 'Category'" :categoryId="selectedId" />
- <CategoryChildrenOptionsPanel v-if="selectedType === 'Category'" :categoryId="selectedId" />
- </div>
- </div>
-
- <DeleteQuestModal
- v-if="selectedType === 'Quest' && selectedId"
- v-model="showDeleteModal"
- :key="`delete-quest-${selectedId}`"
- :questId="selectedId"
- @delete="() => selectedId && deleteQuest(selectedId)"
- />
- <RenameQuestModal
- v-if="selectedType === 'Quest' && selectedId"
- v-model="showRenameModal"
- :key="`rename-quest-${selectedId}`"
- :questId="selectedId"
- @update="newId => selectedId && renameQuest(selectedId, newId)"
- />
- <DuplicateQuestModal
- v-if="selectedType === 'Quest' && selectedId"
- v-model="showDuplicateModal"
- :key="`duplicate-quest-${selectedId}`"
- :questId="selectedId"
- @duplicate="newId => selectedId && duplicateQuest(selectedId, newId)"
- />
-</template>
-
-<style scoped>
-#header {
- padding: 1rem 1rem 0.5rem 1rem;
- background-color: var(--color-background);
- border-bottom: 1px solid var(--color-border);
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
- width: 100%;
- height: 55px;
- display: flex;
- align-items: left;
- justify-content: space-between;
- gap: 1rem;
-
- #path {
- font-size: 1.2rem;
- display: flex;
- gap: 0.5rem;
- align-items: center;
-
- .icon {
- font-size: 0.8rem;
- }
-
- .chevron {
- font-size: 0.8rem;
- color: var(--color-text-mute);
- }
-
- .title {
- font-weight: 700;
- }
-
- code {
- font-size: 0.8rem;
- color: var(--color-text-mute);
- }
- }
-}
-
-.none-selected {
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 1rem;
- font-size: 1.2rem;
- color: var(--color-text-mute);
-}
-
-#pane-container {
- width: 100%;
- flex-grow: 1;
- height: calc(100vh - 73px);
- max-height: calc(100vh - 73px);
-}
-
-#options-container {
- width: 100%;
- display: flex;
- gap: 1rem;
- padding: 1rem;
- overflow: scroll;
- max-height: calc(100% - 55px);
-}
-
-header {
- border-bottom: 1px solid var(--color-border);
-}
-</style> \ No newline at end of file
diff --git a/src/components/Editor/EditorSidebar.vue b/src/components/Editor/EditorSidebar.vue
deleted file mode 100644
index c9539fa..0000000
--- a/src/components/Editor/EditorSidebar.vue
+++ /dev/null
@@ -1,28 +0,0 @@
-<script setup lang="ts">
-import { useSessionStore } from '@/stores/session';
-import { storeToRefs } from 'pinia';
-import EditorSidebarCategory from '@/components/Editor/EditorSidebarCategory.vue';
-import EditorSidebarQuest from '@/components/Editor/EditorSidebarQuest.vue';
-
-const sessionStore = useSessionStore();
-
-const { session } = storeToRefs(sessionStore);
-</script>
-
-<template>
- <div id="sidebar-container">
- <EditorSidebarCategory v-for="category in session.categories" :key="category.id" :category="category" />
- <EditorSidebarQuest v-for="quest in session.quests.filter((q) => (!session.categories.some((c) => c.id === q.options.category)))" :key="quest.id" :quest="quest" />
- </div>
-</template>
-
-<style scoped>
-#sidebar-container {
- width: 20rem;
- border-right: 1px solid var(--color-border);
- height: calc(100vh - 73px);
- max-height: calc(100vh - 73px);
- background-color: var(--color-background);
- user-select: none;
-}
-</style> \ No newline at end of file
diff --git a/src/components/Editor/EditorSidebarCategory.vue b/src/components/Editor/EditorSidebarCategory.vue
deleted file mode 100644
index 7153b92..0000000
--- a/src/components/Editor/EditorSidebarCategory.vue
+++ /dev/null
@@ -1,94 +0,0 @@
-<script setup lang="ts">
-import { useSessionStore, type EditorCategory } from '@/stores/session';
-import { computed, ref, toRefs } from 'vue';
-import { stripColorCodes } from '@/lib/util';
-import EditorSidebarQuest from '@/components/Editor/EditorSidebarQuest.vue';
-
-const props = defineProps<{
- category: EditorCategory;
-}>();
-
-const { category } = toRefs(props);
-
-const expanded = ref(true);
-
-const sessionStore = useSessionStore();
-
-const questsInCategory = computed(() => {
- return sessionStore.getQuestsInCategory(category.value.id);
-});
-
-const expandCategory = () => {
- expanded.value = !expanded.value;
-};
-
-const setSelectedCategory = () => {
- sessionStore.setEditorSelected('Category', category.value.id);
-};
-
-const selected = computed(() => {
- return sessionStore.editor.selected.type === 'Category' && sessionStore.editor.selected.id === category.value.id;
-});
-</script>
-
-<template>
- <div id="category-container" :class="{selected: selected}">
- <span id="category-title" @click="setSelectedCategory">
- <font-awesome-icon @click.stop="expandCategory" class="category-icon" :icon="expanded ? ['fas', 'fa-caret-down'] : ['fas', 'fa-caret-up']"/>
- <span id="category-name">
- <span id="category-display-name">{{ stripColorCodes(category.display.name) }}</span>
- <code id="category-display-id">{{ category.id }}</code>
- </span>
- </span>
- </div>
- <div v-if="expanded" id="quests">
- <EditorSidebarQuest class="quest" v-for="quest in questsInCategory" :key="quest.id" :quest="quest" />
- </div>
-</template>
-
-<style scoped>
-#category-container {
- cursor: pointer;
- padding: 0.5rem 1rem;
- transition: background-color 0.3s;
- border-bottom: 1px solid var(--color-border-soft);
-
- #category-title {
- display: flex;
- align-items: center;
- margin: 0;
- gap: 1rem;
- font-size: 1.1rem;
-
- #category-name {
- display: flex;
- flex-direction: column;
- align-items: left;
-
- #category-display-id {
- font-size: 0.8rem;
- color: var(--color-text-mute);
- }
- }
- }
-}
-
-.selected {
- background-color: var(--color-primary-mute);
-}
-
-#quests {
- background-color: var(--color-background-mute);
- border-bottom: 1px solid var(--color-border-soft);
-}
-
-.quest {
- margin: 0 0 0 1.4rem;
- background-color: var(--color-background);
- border-left: 1px solid var(--color-border);
-}
-
-#category-container:hover {
- background-color: var(--color-hover);
-}
-</style> \ No newline at end of file
diff --git a/src/components/Editor/EditorSidebarQuest.vue b/src/components/Editor/EditorSidebarQuest.vue
deleted file mode 100644
index baf06f1..0000000
--- a/src/components/Editor/EditorSidebarQuest.vue
+++ /dev/null
@@ -1,68 +0,0 @@
-<script setup lang="ts">
-import { useSessionStore, type EditorQuest } from '@/stores/session';
-import { computed, toRefs } from 'vue';
-import { stripColorCodes } from '@/lib/util';
-
-const props = defineProps<{
- quest: EditorQuest;
-}>();
-
-const { quest } = toRefs(props);
-
-const sessionStore = useSessionStore();
-
-const setSelectedQuest = () => {
- sessionStore.setEditorSelected('Quest', quest.value.id);
-};
-
-const selected = computed(() => {
- return sessionStore.editor.selected.type === 'Quest' && sessionStore.editor.selected.id === quest.value.id;
-});
-</script>
-
-<template>
- <div id="quest-container" @click.stop="setSelectedQuest" :class="{selected: selected}">
- <span id="quest-title">
- <font-awesome-icon class="quest-icon" :icon="['far', 'fa-compass']"/>
- <span id="quest-name">
- <span id="quest-display-name">{{ stripColorCodes(quest.display.name) }}</span>
- <code id="quest-display-id">{{ quest.id }}</code>
- </span>
- </span>
- </div>
-</template>
-
-<style scoped>
-#quest-container {
- cursor: pointer;
- padding: 0.3rem 1rem;
- transition: background-color 0.3s;
-
- #quest-title {
- display: flex;
- align-items: center;
- margin: 0;
- gap: 0.5rem;
- font-size: 0.8rem;
-
- #quest-name {
- display: flex;
- flex-direction: column;
- align-items: left;
-
- #quest-display-id {
- font-size: 0.6rem;
- color: var(--color-text-mute);
- }
- }
- }
-}
-
-.selected {
- background-color: var(--color-primary-mute) !important;
-}
-
-#quest-container:hover {
- background-color: var(--color-hover);
-}
-</style> \ No newline at end of file
diff --git a/src/components/Editor/Quest/Modal/DeleteQuestModal.vue b/src/components/Editor/Quest/Modal/DeleteQuestModal.vue
deleted file mode 100644
index d0b0c5a..0000000
--- a/src/components/Editor/Quest/Modal/DeleteQuestModal.vue
+++ /dev/null
@@ -1,42 +0,0 @@
-<script setup lang="ts">
-import Modal from '@/components/Control/Modal.vue';
-import Button from '@/components/Control/Button.vue';
-
-const model = defineModel();
-
-const emit = defineEmits(['delete']);
-
-defineProps({
- questId: String,
-});
-</script>
-
-<template>
- <Modal v-model="model">
- <template v-slot:header>
- <h2>Really delete quest '{{ questId }}'?</h2>
- </template>
- <p>Are you sure you want to delete this quest? The quests editor does not have undo functionality (yet)! </p>
- <div id="confirm" class="control-group">
- <Button
- :icon="['fas', 'fa-times']"
- :label="'Cancel'"
- @click="model = false"
- ></Button>
- <Button
- type="solid"
- :icon="['fas', 'fa-trash']"
- :label="'Delete'"
- @click="emit('delete')"
- ></Button>
- </div>
- </Modal>
-</template>
-
-<style scoped>
-#confirm {
- display: flex;
- justify-content: flex-end;
- margin-top: 1rem;
-}
-</style> \ No newline at end of file
diff --git a/src/components/Editor/Quest/Modal/DuplicateQuestModal.vue b/src/components/Editor/Quest/Modal/DuplicateQuestModal.vue
deleted file mode 100644
index bcd3782..0000000
--- a/src/components/Editor/Quest/Modal/DuplicateQuestModal.vue
+++ /dev/null
@@ -1,69 +0,0 @@
-<script setup lang="ts">
-import Modal from '@/components/Control/Modal.vue';
-import Button from '@/components/Control/Button.vue';
-import { computed, ref } from 'vue';
-import { useSessionStore } from '@/stores/session';
-
-const model = defineModel();
-
-const emit = defineEmits(['duplicate']);
-
-const props = defineProps({
- questId: String,
-});
-
-const session = useSessionStore();
-
-const newQuestId = ref(props.questId);
-
-const isDuplicate = computed(() => {
- return session.getQuestById(newQuestId.value!) !== undefined;
-});
-
-</script>
-
-<template>
- <Modal v-model="model">
- <template v-slot:header>
- <h2>Duplicate '{{ questId }}'</h2>
- </template>
-
- <template v-slot:body>
- <div id="body">
- <div class="option-group">
- <label for="new-type">ID of new quest</label>
- <input id="new-type" name="new-type" type="text" v-model="newQuestId" />
- </div>
- <p v-if="isDuplicate" class="error-text">Name is not unique.</p>
- <p>A Quest ID must be unique, alphanumeric, and not contain any spaces.</p>
- <div id="confirm" class="control-group">
- <Button
- :icon="['fas', 'fa-times']"
- :label="'Cancel'"
- @click="model = false"
- ></Button>
- <Button
- type="solid"
- :icon="['fas', 'fa-check']"
- :label="'Duplicate'"
- :disabled="isDuplicate"
- @click="emit('duplicate', newQuestId)"
- ></Button>
- </div>
- </div>
- </template>
- </Modal>
-</template>
-
-<style scoped>
-#confirm {
- display: flex;
- justify-content: flex-end;
-}
-
-#body {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-}
-</style> \ No newline at end of file
diff --git a/src/components/Editor/Quest/Modal/RenameQuestModal.vue b/src/components/Editor/Quest/Modal/RenameQuestModal.vue
deleted file mode 100644
index 2ad1481..0000000
--- a/src/components/Editor/Quest/Modal/RenameQuestModal.vue
+++ /dev/null
@@ -1,69 +0,0 @@
-<script setup lang="ts">
-import Modal from '@/components/Control/Modal.vue';
-import Button from '@/components/Control/Button.vue';
-import { computed, ref } from 'vue';
-import { useSessionStore } from '@/stores/session';
-
-const model = defineModel();
-
-const emit = defineEmits(['update']);
-
-const props = defineProps({
- questId: String,
-});
-
-const session = useSessionStore();
-
-const newQuestId = ref(props.questId);
-
-const isDuplicate = computed(() => {
- return session.getQuestById(newQuestId.value!) !== undefined;
-});
-
-</script>
-
-<template>
- <Modal v-model="model">
- <template v-slot:header>
- <h2>Rename quest '{{ questId }}'</h2>
- </template>
-
- <template v-slot:body>
- <div id="body">
- <div class="option-group">
- <label for="new-type">New quest ID</label>
- <input id="new-type" name="new-type" type="text" v-model="newQuestId" />
- </div>
- <p v-if="isDuplicate" class="error-text">Name is not unique.</p>
- <p>A Quest ID must be unique, alphanumeric, and not contain any spaces.</p>
- <div id="confirm" class="control-group">
- <Button
- :icon="['fas', 'fa-times']"
- :label="'Cancel'"
- @click="model = false"
- ></Button>
- <Button
- type="solid"
- :icon="['fas', 'fa-check']"
- :label="'Rename'"
- :disabled="isDuplicate"
- @click="emit('update', newQuestId)"
- ></Button>
- </div>
- </div>
- </template>
- </Modal>
-</template>
-
-<style scoped>
-#confirm {
- display: flex;
- justify-content: flex-end;
-}
-
-#body {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-}
-</style> \ No newline at end of file
diff --git a/src/components/Editor/Quest/QuestOptionsPanel.vue b/src/components/Editor/Quest/QuestOptionsPanel.vue
deleted file mode 100644
index a462126..0000000
--- a/src/components/Editor/Quest/QuestOptionsPanel.vue
+++ /dev/null
@@ -1,145 +0,0 @@
-<script setup lang="ts">
-import { useSessionStore, type EditorQuest } from '@/stores/session';
-import { computed, ref } from 'vue';
-import EditorOptionsPanel from '@/components/Editor/EditorOptionsPanel.vue';
-import Checkbox from '@/components/Control/Checkbox.vue';
-
-const props = defineProps<{
- questId: string;
-}>();
-
-const sessionStore = useSessionStore();
-
-const quest = computed(() => {
- return sessionStore.getQuestById(props.questId) as EditorQuest;
-});
-const knownCategories = computed(() => {
- return sessionStore.session.categories.map((category) => category.id);
-});
-const knownQuests = computed(() => {
- return sessionStore.session.quests.map((quest) => quest.id);
-});
-
-</script>
-
-<template>
- <EditorOptionsPanel v-if="quest">
- <div id="options">
- <div class="option-group">
- <label for="quest-category">Category</label>
- <multiselect
- id="quest-category"
- v-model="quest.options.category"
- :options="knownCategories"
- :searchable="true"
- placeholder="No category"></multiselect>
- </div>
-
- <div class="option-group">
- <label for="quest-requirements">Requirements</label>
- <multiselect
- id="quest-requirements"
- v-model="quest.options.requirements"
- :options="knownQuests"
- :searchable="true"
- :taggable="true"
- :multiple="true"
- placeholder="Add requirement"></multiselect>
- <p class="description">
- This quest will only be available if the player has completed all of the quests listed above.
- </p>
- </div>
-
- <h2>Quest options</h2>
-
- <div class="option-group">
- <Checkbox id="quest-permissionrequired" label="Require permission to start quest"
- description="Players must have permission to start the quest." v-model="quest.options.permissionRequired" />
- </div>
-
- <div class="option-group">
- <Checkbox id="quest-cancellable" label="Allow players to cancel quest"
- description="Players can cancel the quest after they have started it." v-model="quest.options.cancellable" />
- </div>
-
- <div class="option-group">
- <Checkbox id="quest-countstowardslimit" label="Count towards quest limit"
- description="Quest will count towards the player's quest started limit."
- v-model="quest.options.countsTowardsLimit" />
- </div>
-
- <div class="option-group">
- <Checkbox id="quest-repeatable" label="Allow players to repeat quest"
- description="Quest can be completed again after it has been completed once."
- v-model="quest.options.repeatable" />
- </div>
-
- <div class="option-group">
- <Checkbox id="quest-autostart" label="Automatically start quest"
- description="Quest will start automatically when the player has unlocked it."
- v-model="quest.options.autostart" />
- </div>
-
-
- <h2>Cooldown</h2>
-
- <div class="option-group">
- <Checkbox id="quest-cooldown" label="Enable cooldown"
- description="Players will have to wait a certain amount of time before they can start the quest again."
- v-model="quest.options.cooldown.enabled" />
- </div>
-
- <div class="option-group">
- <label for="quest-cooldown-time">
- Cooldown (in seconds)
- </label>
- <input id="quest-cooldown-time" type="number" v-model="quest.options.cooldown.time"
- :disabled="!quest.options.cooldown.enabled" />
- <p class="description">
- Common values are: <code>3600</code> (1 hour), <code>86400</code> (24 hours), <code>604800</code> (7 days),
- <code>2592000</code> (30 days)
- </p>
- </div>
-
- <h2>Time limit</h2>
-
- <div class="option-group">
- <Checkbox id="quest-timelimit" label="Enable time limit"
- description="Players will be required to complete the quest within a certain amount of time, otherwise it will be automatically cancelled."
- v-model="quest.options.timeLimit.enabled" />
- </div>
-
- <div class="option-group">
- <label for="quest-timelimit-time">
- Time limit (in seconds)
- </label>
- <input id="quest-timelimit-time" type="number" v-model="quest.options.timeLimit.time"
- :disabled="!quest.options.timeLimit.enabled" />
- <p class="description">
- Common values are: <code>3600</code> (1 hour), <code>86400</code> (24 hours), <code>604800</code> (7 days),
- <code>2592000</code> (30 days)
- </p>
- </div>
- </div>
- </EditorOptionsPanel>
-</template>
-
-<style src="vue-multiselect/dist/vue-multiselect.css" />
-
-<style>
-#options {
- display: flex;
- flex-direction: column;
- gap: 1rem;
-}
-
-.description {
- font-size: 0.8em;
-}
-
-h2 {
- border-bottom: 1px solid var(--color-border);
-}
-
-</style>
-
diff --git a/src/components/Editor/Quest/QuestTasksOptionsPanel.vue b/src/components/Editor/Quest/QuestTasksOptionsPanel.vue
deleted file mode 100644
index a79e636..0000000
--- a/src/components/Editor/Quest/QuestTasksOptionsPanel.vue
+++ /dev/null
@@ -1,98 +0,0 @@
-<script setup lang="ts">
-import { useSessionStore, type EditorQuest } from '@/stores/session';
-import { computed, ref } from 'vue';
-import EditorOptionsPanel from '@/components/Editor/EditorOptionsPanel.vue';
-import TaskConfiguration from '@/components/Editor/Quest/Task/TaskConfiguration.vue';
-import Button from '@/components/Control/Button.vue';
-import AddTaskModal from './Task/Modal/AddTaskModal.vue';
-
-const props = defineProps<{
- questId: string;
-}>();
-
-const sessionStore = useSessionStore();
-
-const quest = computed(() => {
- return sessionStore.getQuestById(props.questId) as EditorQuest;
-});
-
-const showAddTaskModal = ref(false);
-
-const addTask = (newId: string, newType: string) => {
- sessionStore.getQuestById(props.questId)!.tasks[newId] = {
- id: newId,
- config: {
- type: newType,
- },
- };
-
- showAddTaskModal.value = false;
-};
-</script>
-
-<template>
- <EditorOptionsPanel v-if="quest">
- <div id="options">
- <h2>Tasks <code>({{ Object.keys(quest.tasks).length }})</code></h2>
-
- <p v-if="Object.keys(quest.tasks).length === 0" class="error-text">This quest does not have any tasks.</p>
- <TaskConfiguration v-for="(task, taskId) in quest.tasks" :key="taskId" :taskId="String(taskId)" :quest="quest" />
-
- <div id="controls">
- <Button
- id="add-task"
- :icon="['fas', 'fa-plus']"
- type="solid"
- label="Add task"
- @click="showAddTaskModal = true"
- />
- </div>
- </div>
- </EditorOptionsPanel>
-
- <AddTaskModal
- v-if="quest"
- v-model="showAddTaskModal"
- :questId="questId"
- @add="addTask"
- />
-</template>
-
-
-<style scoped>
-#options {
- display: flex;
- flex-direction: column;
- gap: 1rem;
-
- #controls {
- display: flex;
- justify-content: flex-end;
- gap: 1rem;
- }
-}
-
-.option-group {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-}
-
-.description {
- font-size: 0.8em;
-}
-
-label {
- font-weight: 700;
-}
-
-h2 {
- border-bottom: 1px solid var(--color-border);
-
- code {
- font-size: 0.8em;
- color: var(--color-text-mute);
- }
-}
-</style>
-
diff --git a/src/components/Editor/Quest/Task/Modal/AddTaskModal.vue b/src/components/Editor/Quest/Task/Modal/AddTaskModal.vue
deleted file mode 100644
index 57139bb..0000000
--- a/src/components/Editor/Quest/Task/Modal/AddTaskModal.vue
+++ /dev/null
@@ -1,90 +0,0 @@
-<script setup lang="ts">
-import Modal from '@/components/Control/Modal.vue';
-import Button from '@/components/Control/Button.vue';
-import { computed, ref } from 'vue';
-import { useSessionStore } from '@/stores/session';
-import { validateTaskId } from '@/lib/util';
-
-const model = defineModel();
-
-const emit = defineEmits(['add']);
-
-const session = useSessionStore();
-
-const props = defineProps({
- questId: {
- type: String,
- required: true,
- },
-});
-
-const knownTasks = computed(() => session.getQuestById(props.questId)!.tasks);
-const knownTaskTypes = computed(() => session.getKnownTaskTypes());
-
-const newId = ref('');
-const newType = ref('');
-const unknownTaskType = computed(() => !knownTaskTypes.value.includes(newType.value));
-const invalidTaskId = computed(() => !validateTaskId(newId.value));
-const duplicateTaskId = computed(() => knownTasks.value[newId.value] !== undefined);
-
-const newTypeDescription = computed(() => session.getTaskDefinitionByTaskType(newType.value)?.description);
-</script>
-
-<template>
- <Modal v-model="model">
- <template v-slot:header>
- <h2>Add new task</h2>
- </template>
-
- <template v-slot:body>
- <div id="body">
- <div class="option-group">
- <label for="new-type">Task ID</label>
- <input id="new-id" name="new-id" type="text" v-model="newId" />
- <p v-if="invalidTaskId" class="error-text">Invalid task ID.</p>
- <p v-if="duplicateTaskId" class="error-text">Task ID already exists.</p>
- </div>
- <div class="option-group">
- <label for="new-type">Task type</label>
- <multiselect
- id="new-type"
- v-model="newType"
- :options="knownTaskTypes"
- :searchable="true"
- placeholder="Select a new type"
- ></multiselect>
- <p v-if="unknownTaskType" class="error-text">Invalid task type.</p>
- </div>
- <p v-if="newTypeDescription">{{ newTypeDescription }}</p>
- <p>A task ID must be unique, alphanumeric, and not contain any spaces.</p>
- <div id="confirm" class="control-group">
- <Button
- :icon="['fas', 'fa-times']"
- :label="'Cancel'"
- @click="model = false"
- ></Button>
- <Button
- type="solid"
- :icon="['fas', 'fa-check']"
- :label="'Confirm'"
- :disabled="unknownTaskType || invalidTaskId || duplicateTaskId"
- @click="emit('add', newId, newType)"
- ></Button>
- </div>
- </div>
- </template>
- </Modal>
-</template>
-
-<style scoped>
-#confirm {
- display: flex;
- justify-content: flex-end;
-}
-
-#body {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-}
-</style> \ No newline at end of file
diff --git a/src/components/Editor/Quest/Task/Modal/ChangeTaskModal.vue b/src/components/Editor/Quest/Task/Modal/ChangeTaskModal.vue
deleted file mode 100644
index c6b5921..0000000
--- a/src/components/Editor/Quest/Task/Modal/ChangeTaskModal.vue
+++ /dev/null
@@ -1,77 +0,0 @@
-<script setup lang="ts">
-import Modal from '@/components/Control/Modal.vue';
-import Button from '@/components/Control/Button.vue';
-import { computed, ref } from 'vue';
-import { useSessionStore } from '@/stores/session';
-
-const model = defineModel();
-
-const emit = defineEmits(['update']);
-
-const session = useSessionStore();
-
-const props = defineProps({
- taskId: String,
- currentTaskType: String,
-});
-
-const knownTaskTypes = computed(() => session.getKnownTaskTypes());
-
-const newType = ref('');
-const unknownTaskType = computed(() => !knownTaskTypes.value.includes(newType.value));
-const noChange = computed(() => newType.value === props.currentTaskType);
-const newTypeDescription = computed(() => session.getTaskDefinitionByTaskType(newType.value)?.description);
-</script>
-
-<template>
- <Modal v-model="model">
- <template v-slot:header>
- <h2>Change the task type of '{{ taskId }}'</h2>
- </template>
-
- <template v-slot:body>
- <div id="body">
- <div class="option-group">
- <label for="new-type">New type</label>
- <multiselect
- id="new-type"
- v-model="newType"
- :options="knownTaskTypes"
- :searchable="true"
- placeholder="Select a new type"
- ></multiselect>
- </div>
- <p v-if="unknownTaskType" class="error-text">Invalid task type.</p>
- <p v-if="newTypeDescription">{{ newTypeDescription }}</p>
- <p>Any configured options for this task will be overwritten.</p>
- <div id="confirm" class="control-group">
- <Button
- :icon="['fas', 'fa-times']"
- :label="'Cancel'"
- @click="model = false"
- ></Button>
- <Button
- type="solid"
- :icon="['fas', 'fa-check']"
- :label="'Change'"
- :disabled="unknownTaskType || noChange"
- @click="emit('update', newType)"
- ></Button>
- </div>
- </div>
- </template>
- </Modal>
-</template>
-
-<style scoped>
-#confirm {
- display: flex;
- justify-content: flex-end;
-}
-
-#body {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-}
-</style> \ No newline at end of file
diff --git a/src/components/Editor/Quest/Task/TaskConfiguration.vue b/src/components/Editor/Quest/Task/TaskConfiguration.vue
deleted file mode 100644
index 0646ad4..0000000
--- a/src/components/Editor/Quest/Task/TaskConfiguration.vue
+++ /dev/null
@@ -1,209 +0,0 @@
-<script setup lang="ts">
-import { useSessionStore, type EditorQuest } from '@/stores/session';
-import { computed, ref } from 'vue';
-import Button from '@/components/Control/Button.vue';
-import TaskConfigurationRow from '@/components/Editor/Quest/Task/TaskConfigurationRow.vue';
-import ChangeTaskModal from './Modal/ChangeTaskModal.vue';
-
-const props = defineProps<{
- taskId: string;
- quest: EditorQuest;
-}>();
-
-const sessionStore = useSessionStore();
-
-const taskType = computed(() => props.quest.tasks[props.taskId].config.type);
-const taskDefintion = computed(() => sessionStore.getTaskDefinitionByTaskType(taskType.value));
-
-const taskConfig = computed(() => {
- return Object.keys(props.quest.tasks[props.taskId].config).filter((fieldName) => fieldName !== 'type').reduce((acc, fieldName) => {
- acc[fieldName] = props.quest.tasks[props.taskId].config[fieldName];
- return acc;
- }, {} as { [key: string]: any });
-});
-
-const requiredFields = computed(() => {
- return Object.keys(taskDefintion.value.configuration).filter((fieldName) => taskDefintion.value.configuration[fieldName].required);
-});
-
-const givenRequiredFields = computed(() => {
- return requiredFields.value.filter((fieldName) => taskConfig.value[fieldName]);
-});
-
-const missingFields = computed(() => {
- return requiredFields.value.filter((fieldName) => !props.quest.tasks[props.taskId].config[fieldName]);
-});
-
-const remainingGivenFields = computed(() => {
- return Object.keys(taskConfig.value).filter((fieldName) => !requiredFields.value.includes(fieldName));
-});
-
-const configKeysOptions = computed(() => Object.keys(taskDefintion.value.configuration).filter((key) => !Object.keys(taskConfig.value).some((fieldName) => fieldName === key)));
-// const configKeysOptions = computed(() => {
-// const keys = Object.keys(taskDefintion.value.configuration).filter((key) => !Object.keys(taskConfig.value).some((fieldName) => fieldName === key));
-//
-// return keys.map((key) => {
-// return {
-// value: key,
-// description: taskDefintion.value.configuration[key].description,
-// note: taskDefintion.value.configuration[key].note,
-// };
-// });
-// });
-
-const onAddOption = (option: any) => {
- sessionStore.getQuestById(props.quest.id)!.tasks[props.taskId].config[option] = taskDefintion.value.configuration[option].default || null;
-};
-
-const updateValue = (fieldName: string, value: any) => {
- sessionStore.getQuestById(props.quest.id)!.tasks[props.taskId].config[fieldName] = value;
-};
-
-const deleteValue = (fieldName: string) => {
- delete sessionStore.getQuestById(props.quest.id)!.tasks[props.taskId].config[fieldName];
-};
-
-const showChangeModal = ref(false);
-
-const updateTaskType = (newType: string) => {
- sessionStore.getQuestById(props.quest.id)!.tasks[props.taskId].config = {
- type: newType
- };
- showChangeModal.value = false;
-}
-
-const deleteTaskType = (taskId: string) => {
- delete sessionStore.getQuestById(props.quest.id)!.tasks[taskId];
-}
-</script>
-
-<template>
- <div id="task-configuration-table">
- <div id="task-header">
- <p id="task-id">
- <span id="task-name">
- {{ props.taskId }}
- </span>
- <code>
- ({{ taskType }})
- </code>
- </p>
- <div id="task-controls" class="control-group">
- <Button
- :icon="['fas', 'fa-pen']"
- :label="'Change'"
- @click="showChangeModal = true"
- ></Button>
- <Button
- :icon="['fas', 'fa-trash']"
- :label="'Delete'"
- @click="deleteTaskType(props.taskId)"
- ></Button>
- </div>
- </div>
- <div id="task-configuration">
- <div v-if="!taskDefintion" class="error">
- <font-awesome-icon id="error-icon" :icon="['fas', 'fa-triangle-exclamation']"/>
- <p id="error-message">
- Unable to edit task <code>{{ props.taskId }}</code>.
- </p>
- <p id="error-description">
- The quests web editor does not know how to configure task
- type <code>{{ taskType }}</code> as it has no task definition.
- </p>
- </div>
-
- <div v-if="taskDefintion">
- <TaskConfigurationRow
- v-for="fieldName in [...givenRequiredFields, ...missingFields, ...remainingGivenFields]"
- :key="`${quest.id}-${props.taskId}-${taskType}-${fieldName}`"
- :required="requiredFields.includes(fieldName)"
- :configKey="fieldName"
- :initialValue="taskConfig[fieldName]"
- :taskType="taskType"
- :type="(taskDefintion.configuration[fieldName].type as string)"
- @update="newValue => updateValue(fieldName, newValue)"
- @delete="() => deleteValue(fieldName)"
- />
- <div id="add-option">
- <multiselect
- class="multiselect"
- :options="configKeysOptions"
- :searchable="true"
- @select="onAddOption"
- placeholder="Add option...">
- </multiselect>
- </div>
- </div>
- </div>
- </div>
-
- <ChangeTaskModal
- v-model="showChangeModal"
- :taskId="props.taskId"
- :currentTaskType="taskType"
- :key="`change-task-${props.taskId}`"
- @update="updateTaskType"
- />
-</template>
-
-<style scoped>
-.error {
- padding: 0.5rem 0.5rem 0.5rem calc(0.5rem + 20px);
-
- #error-icon {
- float: left;
- margin: 5px 0 0 -20px;
- }
-
- #error-message {
- font-weight: 700;
- }
-
-}
-
-#task-configuration-table {
- display: flex;
- flex-direction: column;
- border: 1px solid var(--color-border);
-
- #task-header {
- display: flex;
- justify-content: space-between;
- border-bottom: 1px solid var(--color-border);
- background-color: var(--color-background-soft);
- padding: 0.5rem;
-
- #task-id {
- font-size: 1.2em;
-
- #task-name {
- font-weight: 700;
- }
-
- code {
- font-size: 0.8em;
- color: var(--color-text-mute);
- }
- }
- }
-}
-
-#add-option {
- width: 100%;
- border-right: 1px solid var(--color-border);
- border-top: 1px solid var(--color-border);
-}
-
-.multiselect::v-deep .multiselect__tags {
- border: none !important;
- border-radius: 0px !important;
- background: transparent !important;
-}
-
-.multiselect::v-deep .multiselect__select {
- background: transparent !important;
-}
-
-</style>
-
diff --git a/src/components/Editor/Quest/Task/TaskConfigurationRow.vue b/src/components/Editor/Quest/Task/TaskConfigurationRow.vue
deleted file mode 100644
index f68ce97..0000000
--- a/src/components/Editor/Quest/Task/TaskConfigurationRow.vue
+++ /dev/null
@@ -1,195 +0,0 @@
-<script setup lang="ts">
-import { useSessionStore } from '@/stores/session';
-import { computed, ref, toRefs, watch } from 'vue';
-import TrueFalseSwitch from '@/components/Control/TrueFalseSwitch.vue';
-import ItemStackPicker from '@/components/Control/ItemStackPicker.vue';
-import materials from '@/lib/materials';
-
-const props = defineProps({
- taskType: {
- type: String,
- required: true,
- },
- configKey: {
- type: String,
- required: true,
- },
- initialValue: null,
- type: String,
- required: Boolean,
-});
-const emit = defineEmits(['update', 'delete']);
-
-const sessionStore = useSessionStore();
-
-const definition = computed(() => {
- const def = sessionStore.getTaskDefinitionByTaskType(props.taskType).configuration[props.configKey];
- return { description: def.description, note: def.note };
-});
-
-const { description, note } = toRefs(definition.value);
-const showDescription = ref(false);
-const currentValue = ref(props.initialValue ||
- (props.type === 'boolean'
- ? false
- : (props.type === 'material-list' || props.type === 'string-list'
- ? []
- : props.type === 'itemstack'
- ? null
- : ''
- )));
-
-if (props.initialValue !== currentValue.value) {
- emit('update', currentValue.value);
-}
-
-const error = computed(() => currentValue.value === undefined || currentValue.value === null || currentValue.value === '' || (Array.isArray(currentValue.value) && currentValue.value.length === 0));
-const updateValue = (value: any) => {
- currentValue.value = value;
-};
-
-watch(currentValue, () => {
- emit('update', currentValue.value);
-});
-
-const addValue = (searchQuery: any) => {
- currentValue.value.push(searchQuery);
-};
-
-</script>
-
-<template>
- <div id="task-configuration-row">
- <div id="key">
- <div id="delete" @click="emit('delete')" v-if="!props.required" class="delete">
- <font-awesome-icon :icon="['fas', 'fa-xmark']" />
- </div>
- <p id="name" @click="showDescription = !showDescription">{{ props.configKey }}</p>
- </div>
- <div id="value">
- <div id="value-container">
- <!-- Data type 'string' -->
- <input v-if="props.type === 'string'" v-model="currentValue" />
-
- <!-- Data type 'number' -->
- <input v-else-if="props.type === 'number'" type="number" v-model="currentValue" />
-
- <!-- Data type 'boolean' -->
- <TrueFalseSwitch v-else-if="props.type === 'boolean'" :value="!!currentValue" @update="updateValue" />
-
- <!-- Data type 'material-list' -->
- <multiselect v-else-if="props.type === 'material-list'" v-model="currentValue"
- :options="materials" :multiple="true" :taggable="true" :searchable="true" placeholder="Enter material name" />
-
- <!-- Data type 'string-list' -->
- <multiselect v-else-if="props.type === 'string-list'" v-model="currentValue" :options="[]" @tag="addValue"
- :multiple="true" :taggable="true" :searchable="true" placeholder="Enter string" />
-
- <!-- Data type 'itemstack' -->
- <ItemStackPicker v-else-if="props.type === 'itemstack'" :value="currentValue" @update="updateValue" />
-
- <div v-if="showDescription || error" id="task-configuration-row-info">
- <p v-if="error" class="error">A value is required.</p>
- <p>{{ description }} <i>{{ note }}</i></p>
- </div>
- </div>
- </div>
- </div>
-</template>
-
-<style scoped>
-#task-configuration-row {
- display: flex;
- flex-direction: row;
- transition: background-color 0.3s;
- border-bottom: 1px solid var(--color-border);
-
- #key {
- width: 25%;
- background-color: var(--color-background);
- display: flex;
- flex-direction: row;
- align-items: center;
- user-select: none;
-
- #delete {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 20px;
- height: 100%;
- cursor: pointer;
- color: var(--color-text-mute);
- border-right: 1px solid var(--color-border);
- background-color: var(--color-background-soft);
- transition: color 0.3s;
-
- &:hover {
- color: var(--color-false);
- }
- }
-
- #name {
- display: flex;
- align-items: center;
- font-size: 0.8rem;
- padding: 0.5rem;
- width: 100%;
- height: 100%;
- font-family: monospace;
- cursor: pointer;
- transition: background-color 0.3s;
-
- &:hover {
- background-color: var(--color-hover);
- }
- }
- }
-
- #value {
- width: 75%;
- background-color: var(--color-background);
- border-left: 1px solid var(--color-border);
-
- #value-container {
- display: flex;
- flex-direction: column;
- height: 100%;
- }
- }
-}
-
-#task-configuration-row:hover {
- background-color: var(--color-hover);
-}
-
-#task-configuration-row-info {
- padding: 0.25rem 0.5rem;
- font-size: 0.8em;
- background-color: var(--color-background);
- border-top: 1px solid var(--color-border);
-}
-
-input {
- width: 100%;
- padding: 0.5rem;
- border-radius: 0;
- border: none;
- font-family: monospace;
- font-size: 0.8rem;
- height: 40px;
-}
-
-.error {
- color: var(--color-false);
-}
-
-.multiselect::v-deep .multiselect__tags {
- border: unset !important;
- border-radius: 0px !important;
-}
-
-.multiselect::v-deep .multiselect__select {
- background: unset !important;
-}
-</style> \ No newline at end of file
diff --git a/src/components/Header/SiteHeader.vue b/src/components/Header/SiteHeader.vue
deleted file mode 100644
index f51e970..0000000
--- a/src/components/Header/SiteHeader.vue
+++ /dev/null
@@ -1,43 +0,0 @@
-<template>
- <header>
- <div id="nav">
- <img src="@/assets/quests-logo.png" alt="Quests logo" />
- <h1>Quests Web Editor</h1>
- <code>Preview</code>
- </div>
- </header>
-</template>
-
-<style lang="scss" scoped>
-
-#nav {
- padding: 1rem 1rem 0.5rem 1rem;
- display: flex;
- align-items: center;
- justify-content: flex-start;
- max-height: 72px;
- gap: 1rem;
-
- img {
- max-width: 3rem;
- height: auto;
- }
-
- h1 {
- font-size: 1.5rem;
- margin: -5px 0 0 0;
- font-weight: 700;
- }
-
- code {
- font-size: 0.8rem;
- color: var(--color-text-mute);
- }
-
-}
-
-header {
- border-bottom: 1px solid var(--color-border);
-}
-
-</style> \ No newline at end of file
diff --git a/src/data/materials.json b/src/data/materials.json
deleted file mode 100644
index 1726002..0000000
--- a/src/data/materials.json
+++ /dev/null
@@ -1,1924 +0,0 @@
-[
- "ACACIA_BOAT",
- "ACACIA_BUTTON",
- "ACACIA_CHEST_BOAT",
- "ACACIA_DOOR",
- "ACACIA_FENCE",
- "ACACIA_FENCE_GATE",
- "ACACIA_HANGING_SIGN",
- "ACACIA_LEAVES",
- "ACACIA_LOG",
- "ACACIA_PLANKS",
- "ACACIA_PRESSURE_PLATE",
- "ACACIA_SAPLING",
- "ACACIA_SIGN",
- "ACACIA_SLAB",
- "ACACIA_STAIRS",
- "ACACIA_TRAPDOOR",
- "ACACIA_WALL_HANGING_SIGN",
- "ACACIA_WALL_SIGN",
- "ACACIA_WOOD",
- "ACTIVATOR_RAIL",
- "AIR",
- "ALLAY_SPAWN_EGG",
- "ALLIUM",
- "AMETHYST_BLOCK",
- "AMETHYST_CLUSTER",
- "AMETHYST_SHARD",
- "ANCIENT_DEBRIS",
- "ANDESITE",
- "ANDESITE_SLAB",
- "ANDESITE_STAIRS",
- "ANDESITE_WALL",
- "ANGLER_POTTERY_SHERD",
- "ANVIL",
- "APPLE",
- "ARCHER_POTTERY_SHERD",
- "ARMOR_STAND",
- "ARMS_UP_POTTERY_SHERD",
- "ARROW",
- "ATTACHED_MELON_STEM",
- "ATTACHED_PUMPKIN_STEM",
- "AXOLOTL_BUCKET",
- "AXOLOTL_SPAWN_EGG",
- "AZALEA",
- "AZALEA_LEAVES",
- "AZURE_BLUET",
- "BAKED_POTATO",
- "BAMBOO",
- "BAMBOO_BLOCK",
- "BAMBOO_BUTTON",
- "BAMBOO_CHEST_RAFT",
- "BAMBOO_DOOR",
- "BAMBOO_FENCE",
- "BAMBOO_FENCE_GATE",
- "BAMBOO_HANGING_SIGN",
- "BAMBOO_MOSAIC",
- "BAMBOO_MOSAIC_SLAB",
- "BAMBOO_MOSAIC_STAIRS",
- "BAMBOO_PLANKS",
- "BAMBOO_PRESSURE_PLATE",
- "BAMBOO_RAFT",
- "BAMBOO_SAPLING",
- "BAMBOO_SIGN",
- "BAMBOO_SLAB",
- "BAMBOO_STAIRS",
- "BAMBOO_TRAPDOOR",
- "BAMBOO_WALL_HANGING_SIGN",
- "BAMBOO_WALL_SIGN",
- "BARREL",
- "BARRIER",
- "BASALT",
- "BAT_SPAWN_EGG",
- "BEACON",
- "BEDROCK",
- "BEE_NEST",
- "BEE_SPAWN_EGG",
- "BEEF",
- "BEEHIVE",
- "BEETROOT",
- "BEETROOT_SEEDS",
- "BEETROOT_SOUP",
- "BEETROOTS",
- "BELL",
- "BIG_DRIPLEAF",
- "BIG_DRIPLEAF_STEM",
- "BIRCH_BOAT",
- "BIRCH_BUTTON",
- "BIRCH_CHEST_BOAT",
- "BIRCH_DOOR",
- "BIRCH_FENCE",
- "BIRCH_FENCE_GATE",
- "BIRCH_HANGING_SIGN",
- "BIRCH_LEAVES",
- "BIRCH_LOG",
- "BIRCH_PLANKS",
- "BIRCH_PRESSURE_PLATE",
- "BIRCH_SAPLING",
- "BIRCH_SIGN",
- "BIRCH_SLAB",
- "BIRCH_STAIRS",
- "BIRCH_TRAPDOOR",
- "BIRCH_WALL_HANGING_SIGN",
- "BIRCH_WALL_SIGN",
- "BIRCH_WOOD",
- "BLACK_BANNER",
- "BLACK_BED",
- "BLACK_CANDLE",
- "BLACK_CANDLE_CAKE",
- "BLACK_CARPET",
- "BLACK_CONCRETE",
- "BLACK_CONCRETE_POWDER",
- "BLACK_DYE",
- "BLACK_GLAZED_TERRACOTTA",
- "BLACK_SHULKER_BOX",
- "BLACK_STAINED_GLASS",
- "BLACK_STAINED_GLASS_PANE",
- "BLACK_TERRACOTTA",
- "BLACK_WALL_BANNER",
- "BLACK_WOOL",
- "BLACKSTONE",
- "BLACKSTONE_SLAB",
- "BLACKSTONE_STAIRS",
- "BLACKSTONE_WALL",
- "BLADE_POTTERY_SHERD",
- "BLAST_FURNACE",
- "BLAZE_POWDER",
- "BLAZE_ROD",
- "BLAZE_SPAWN_EGG",
- "BLUE_BANNER",
- "BLUE_BED",
- "BLUE_CANDLE",
- "BLUE_CANDLE_CAKE",
- "BLUE_CARPET",
- "BLUE_CONCRETE",
- "BLUE_CONCRETE_POWDER",
- "BLUE_DYE",
- "BLUE_GLAZED_TERRACOTTA",
- "BLUE_ICE",
- "BLUE_ORCHID",
- "BLUE_SHULKER_BOX",
- "BLUE_STAINED_GLASS",
- "BLUE_STAINED_GLASS_PANE",
- "BLUE_TERRACOTTA",
- "BLUE_WALL_BANNER",
- "BLUE_WOOL",
- "BONE",
- "BONE_BLOCK",
- "BONE_MEAL",
- "BOOK",
- "BOOKSHELF",
- "BOW",
- "BOWL",
- "BRAIN_CORAL",
- "BRAIN_CORAL_BLOCK",
- "BRAIN_CORAL_FAN",
- "BRAIN_CORAL_WALL_FAN",
- "BREAD",
- "BREEZE_SPAWN_EGG",
- "BREWER_POTTERY_SHERD",
- "BREWING_STAND",
- "BRICK",
- "BRICK_SLAB",
- "BRICK_STAIRS",
- "BRICK_WALL",
- "BRICKS",
- "BROWN_BANNER",
- "BROWN_BED",
- "BROWN_CANDLE",
- "BROWN_CANDLE_CAKE",
- "BROWN_CARPET",
- "BROWN_CONCRETE",
- "BROWN_CONCRETE_POWDER",
- "BROWN_DYE",
- "BROWN_GLAZED_TERRACOTTA",
- "BROWN_MUSHROOM",
- "BROWN_MUSHROOM_BLOCK",
- "BROWN_SHULKER_BOX",
- "BROWN_STAINED_GLASS",
- "BROWN_STAINED_GLASS_PANE",
- "BROWN_TERRACOTTA",
- "BROWN_WALL_BANNER",
- "BROWN_WOOL",
- "BRUSH",
- "BUBBLE_COLUMN",
- "BUBBLE_CORAL",
- "BUBBLE_CORAL_BLOCK",
- "BUBBLE_CORAL_FAN",
- "BUBBLE_CORAL_WALL_FAN",
- "BUCKET",
- "BUDDING_AMETHYST",
- "BUNDLE",
- "BURN_POTTERY_SHERD",
- "CACTUS",
- "CAKE",
- "CALCITE",
- "CALIBRATED_SCULK_SENSOR",
- "CAMEL_SPAWN_EGG",
- "CAMPFIRE",
- "CANDLE",
- "CANDLE_CAKE",
- "CARROT",
- "CARROT_ON_A_STICK",
- "CARROTS",
- "CARTOGRAPHY_TABLE",
- "CARVED_PUMPKIN",
- "CAT_SPAWN_EGG",
- "CAULDRON",
- "CAVE_AIR",
- "CAVE_SPIDER_SPAWN_EGG",
- "CAVE_VINES",
- "CAVE_VINES_PLANT",
- "CHAIN",
- "CHAIN_COMMAND_BLOCK",
- "CHAINMAIL_BOOTS",
- "CHAINMAIL_CHESTPLATE",
- "CHAINMAIL_HELMET",
- "CHAINMAIL_LEGGINGS",
- "CHARCOAL",
- "CHERRY_BOAT",
- "CHERRY_BUTTON",
- "CHERRY_CHEST_BOAT",
- "CHERRY_DOOR",
- "CHERRY_FENCE",
- "CHERRY_FENCE_GATE",
- "CHERRY_HANGING_SIGN",
- "CHERRY_LEAVES",
- "CHERRY_LOG",
- "CHERRY_PLANKS",
- "CHERRY_PRESSURE_PLATE",
- "CHERRY_SAPLING",
- "CHERRY_SIGN",
- "CHERRY_SLAB",
- "CHERRY_STAIRS",
- "CHERRY_TRAPDOOR",
- "CHERRY_WALL_HANGING_SIGN",
- "CHERRY_WALL_SIGN",
- "CHERRY_WOOD",
- "CHEST",
- "CHEST_MINECART",
- "CHICKEN",
- "CHICKEN_SPAWN_EGG",
- "CHIPPED_ANVIL",
- "CHISELED_BOOKSHELF",
- "CHISELED_COPPER",
- "CHISELED_DEEPSLATE",
- "CHISELED_NETHER_BRICKS",
- "CHISELED_POLISHED_BLACKSTONE",
- "CHISELED_QUARTZ_BLOCK",
- "CHISELED_RED_SANDSTONE",
- "CHISELED_SANDSTONE",
- "CHISELED_STONE_BRICKS",
- "CHISELED_TUFF",
- "CHISELED_TUFF_BRICKS",
- "CHORUS_FLOWER",
- "CHORUS_FRUIT",
- "CHORUS_PLANT",
- "CLAY",
- "CLAY_BALL",
- "CLOCK",
- "COAL",
- "COAL_BLOCK",
- "COAL_ORE",
- "COARSE_DIRT",
- "COAST_ARMOR_TRIM_SMITHING_TEMPLATE",
- "COBBLED_DEEPSLATE",
- "COBBLED_DEEPSLATE_SLAB",
- "COBBLED_DEEPSLATE_STAIRS",
- "COBBLED_DEEPSLATE_WALL",
- "COBBLESTONE",
- "COBBLESTONE_SLAB",
- "COBBLESTONE_STAIRS",
- "COBBLESTONE_WALL",
- "COBWEB",
- "COCOA",
- "COCOA_BEANS",
- "COD",
- "COD_BUCKET",
- "COD_SPAWN_EGG",
- "COMMAND_BLOCK",
- "COMMAND_BLOCK_MINECART",
- "COMPARATOR",
- "COMPASS",
- "COMPOSTER",
- "CONDUIT",
- "COOKED_BEEF",
- "COOKED_CHICKEN",
- "COOKED_COD",
- "COOKED_MUTTON",
- "COOKED_PORKCHOP",
- "COOKED_RABBIT",
- "COOKED_SALMON",
- "COOKIE",
- "COPPER_BLOCK",
- "COPPER_BULB",
- "COPPER_DOOR",
- "COPPER_GRATE",
- "COPPER_INGOT",
- "COPPER_ORE",
- "COPPER_TRAPDOOR",
- "CORNFLOWER",
- "COW_SPAWN_EGG",
- "CRACKED_DEEPSLATE_BRICKS",
- "CRACKED_DEEPSLATE_TILES",
- "CRACKED_NETHER_BRICKS",
- "CRACKED_POLISHED_BLACKSTONE_BRICKS",
- "CRACKED_STONE_BRICKS",
- "CRAFTER",
- "CRAFTING_TABLE",
- "CREEPER_BANNER_PATTERN",
- "CREEPER_HEAD",
- "CREEPER_SPAWN_EGG",
- "CREEPER_WALL_HEAD",
- "CRIMSON_BUTTON",
- "CRIMSON_DOOR",
- "CRIMSON_FENCE",
- "CRIMSON_FENCE_GATE",
- "CRIMSON_FUNGUS",
- "CRIMSON_HANGING_SIGN",
- "CRIMSON_HYPHAE",
- "CRIMSON_NYLIUM",
- "CRIMSON_PLANKS",
- "CRIMSON_PRESSURE_PLATE",
- "CRIMSON_ROOTS",
- "CRIMSON_SIGN",
- "CRIMSON_SLAB",
- "CRIMSON_STAIRS",
- "CRIMSON_STEM",
- "CRIMSON_TRAPDOOR",
- "CRIMSON_WALL_HANGING_SIGN",
- "CRIMSON_WALL_SIGN",
- "CROSSBOW",
- "CRYING_OBSIDIAN",
- "CUT_COPPER",
- "CUT_COPPER_SLAB",
- "CUT_COPPER_STAIRS",
- "CUT_RED_SANDSTONE",
- "CUT_RED_SANDSTONE_SLAB",
- "CUT_SANDSTONE",
- "CUT_SANDSTONE_SLAB",
- "CYAN_BANNER",
- "CYAN_BED",
- "CYAN_CANDLE",
- "CYAN_CANDLE_CAKE",
- "CYAN_CARPET",
- "CYAN_CONCRETE",
- "CYAN_CONCRETE_POWDER",
- "CYAN_DYE",
- "CYAN_GLAZED_TERRACOTTA",
- "CYAN_SHULKER_BOX",
- "CYAN_STAINED_GLASS",
- "CYAN_STAINED_GLASS_PANE",
- "CYAN_TERRACOTTA",
- "CYAN_WALL_BANNER",
- "CYAN_WOOL",
- "DAMAGED_ANVIL",
- "DANDELION",
- "DANGER_POTTERY_SHERD",
- "DARK_OAK_BOAT",
- "DARK_OAK_BUTTON",
- "DARK_OAK_CHEST_BOAT",
- "DARK_OAK_DOOR",
- "DARK_OAK_FENCE",
- "DARK_OAK_FENCE_GATE",
- "DARK_OAK_HANGING_SIGN",
- "DARK_OAK_LEAVES",
- "DARK_OAK_LOG",
- "DARK_OAK_PLANKS",
- "DARK_OAK_PRESSURE_PLATE",
- "DARK_OAK_SAPLING",
- "DARK_OAK_SIGN",
- "DARK_OAK_SLAB",
- "DARK_OAK_STAIRS",
- "DARK_OAK_TRAPDOOR",
- "DARK_OAK_WALL_HANGING_SIGN",
- "DARK_OAK_WALL_SIGN",
- "DARK_OAK_WOOD",
- "DARK_PRISMARINE",
- "DARK_PRISMARINE_SLAB",
- "DARK_PRISMARINE_STAIRS",
- "DAYLIGHT_DETECTOR",
- "DEAD_BRAIN_CORAL",
- "DEAD_BRAIN_CORAL_BLOCK",
- "DEAD_BRAIN_CORAL_FAN",
- "DEAD_BRAIN_CORAL_WALL_FAN",
- "DEAD_BUBBLE_CORAL",
- "DEAD_BUBBLE_CORAL_BLOCK",
- "DEAD_BUBBLE_CORAL_FAN",
- "DEAD_BUBBLE_CORAL_WALL_FAN",
- "DEAD_BUSH",
- "DEAD_FIRE_CORAL",
- "DEAD_FIRE_CORAL_BLOCK",
- "DEAD_FIRE_CORAL_FAN",
- "DEAD_FIRE_CORAL_WALL_FAN",
- "DEAD_HORN_CORAL",
- "DEAD_HORN_CORAL_BLOCK",
- "DEAD_HORN_CORAL_FAN",
- "DEAD_HORN_CORAL_WALL_FAN",
- "DEAD_TUBE_CORAL",
- "DEAD_TUBE_CORAL_BLOCK",
- "DEAD_TUBE_CORAL_FAN",
- "DEAD_TUBE_CORAL_WALL_FAN",
- "DEBUG_STICK",
- "DECORATED_POT",
- "DEEPSLATE",
- "DEEPSLATE_BRICK_SLAB",
- "DEEPSLATE_BRICK_STAIRS",
- "DEEPSLATE_BRICK_WALL",
- "DEEPSLATE_BRICKS",
- "DEEPSLATE_COAL_ORE",
- "DEEPSLATE_COPPER_ORE",
- "DEEPSLATE_DIAMOND_ORE",
- "DEEPSLATE_EMERALD_ORE",
- "DEEPSLATE_GOLD_ORE",
- "DEEPSLATE_IRON_ORE",
- "DEEPSLATE_LAPIS_ORE",
- "DEEPSLATE_REDSTONE_ORE",
- "DEEPSLATE_TILE_SLAB",
- "DEEPSLATE_TILE_STAIRS",
- "DEEPSLATE_TILE_WALL",
- "DEEPSLATE_TILES",
- "DETECTOR_RAIL",
- "DIAMOND",
- "DIAMOND_AXE",
- "DIAMOND_BLOCK",
- "DIAMOND_BOOTS",
- "DIAMOND_CHESTPLATE",
- "DIAMOND_HELMET",
- "DIAMOND_HOE",
- "DIAMOND_HORSE_ARMOR",
- "DIAMOND_LEGGINGS",
- "DIAMOND_ORE",
- "DIAMOND_PICKAXE",
- "DIAMOND_SHOVEL",
- "DIAMOND_SWORD",
- "DIORITE",
- "DIORITE_SLAB",
- "DIORITE_STAIRS",
- "DIORITE_WALL",
- "DIRT",
- "DIRT_PATH",
- "DISC_FRAGMENT_5",
- "DISPENSER",
- "DOLPHIN_SPAWN_EGG",
- "DONKEY_SPAWN_EGG",
- "DRAGON_BREATH",
- "DRAGON_EGG",
- "DRAGON_HEAD",
- "DRAGON_WALL_HEAD",
- "DRIED_KELP",
- "DRIED_KELP_BLOCK",
- "DRIPSTONE_BLOCK",
- "DROPPER",
- "DROWNED_SPAWN_EGG",
- "DUNE_ARMOR_TRIM_SMITHING_TEMPLATE",
- "ECHO_SHARD",
- "EGG",
- "ELDER_GUARDIAN_SPAWN_EGG",
- "ELYTRA",
- "EMERALD",
- "EMERALD_BLOCK",
- "EMERALD_ORE",
- "ENCHANTED_BOOK",
- "ENCHANTED_GOLDEN_APPLE",
- "ENCHANTING_TABLE",
- "END_CRYSTAL",
- "END_GATEWAY",
- "END_PORTAL",
- "END_PORTAL_FRAME",
- "END_ROD",
- "END_STONE",
- "END_STONE_BRICK_SLAB",
- "END_STONE_BRICK_STAIRS",
- "END_STONE_BRICK_WALL",
- "END_STONE_BRICKS",
- "ENDER_CHEST",
- "ENDER_DRAGON_SPAWN_EGG",
- "ENDER_EYE",
- "ENDER_PEARL",
- "ENDERMAN_SPAWN_EGG",
- "ENDERMITE_SPAWN_EGG",
- "EVOKER_SPAWN_EGG",
- "EXPERIENCE_BOTTLE",
- "EXPLORER_POTTERY_SHERD",
- "EXPOSED_CHISELED_COPPER",
- "EXPOSED_COPPER",
- "EXPOSED_COPPER_BULB",
- "EXPOSED_COPPER_DOOR",
- "EXPOSED_COPPER_GRATE",
- "EXPOSED_COPPER_TRAPDOOR",
- "EXPOSED_CUT_COPPER",
- "EXPOSED_CUT_COPPER_SLAB",
- "EXPOSED_CUT_COPPER_STAIRS",
- "EYE_ARMOR_TRIM_SMITHING_TEMPLATE",
- "FARMLAND",
- "FEATHER",
- "FERMENTED_SPIDER_EYE",
- "FERN",
- "FILLED_MAP",
- "FIRE",
- "FIRE_CHARGE",
- "FIRE_CORAL",
- "FIRE_CORAL_BLOCK",
- "FIRE_CORAL_FAN",
- "FIRE_CORAL_WALL_FAN",
- "FIREWORK_ROCKET",
- "FIREWORK_STAR",
- "FISHING_ROD",
- "FLETCHING_TABLE",
- "FLINT",
- "FLINT_AND_STEEL",
- "FLOWER_BANNER_PATTERN",
- "FLOWER_POT",
- "FLOWERING_AZALEA",
- "FLOWERING_AZALEA_LEAVES",
- "FOX_SPAWN_EGG",
- "FRIEND_POTTERY_SHERD",
- "FROG_SPAWN_EGG",
- "FROGSPAWN",
- "FROSTED_ICE",
- "FURNACE",
- "FURNACE_MINECART",
- "GHAST_SPAWN_EGG",
- "GHAST_TEAR",
- "GILDED_BLACKSTONE",
- "GLASS",
- "GLASS_BOTTLE",
- "GLASS_PANE",
- "GLISTERING_MELON_SLICE",
- "GLOBE_BANNER_PATTERN",
- "GLOW_BERRIES",
- "GLOW_INK_SAC",
- "GLOW_ITEM_FRAME",
- "GLOW_LICHEN",
- "GLOW_SQUID_SPAWN_EGG",
- "GLOWSTONE",
- "GLOWSTONE_DUST",
- "GOAT_HORN",
- "GOAT_SPAWN_EGG",
- "GOLD_BLOCK",
- "GOLD_INGOT",
- "GOLD_NUGGET",
- "GOLD_ORE",
- "GOLDEN_APPLE",
- "GOLDEN_AXE",
- "GOLDEN_BOOTS",
- "GOLDEN_CARROT",
- "GOLDEN_CHESTPLATE",
- "GOLDEN_HELMET",
- "GOLDEN_HOE",
- "GOLDEN_HORSE_ARMOR",
- "GOLDEN_LEGGINGS",
- "GOLDEN_PICKAXE",
- "GOLDEN_SHOVEL",
- "GOLDEN_SWORD",
- "GRANITE",
- "GRANITE_SLAB",
- "GRANITE_STAIRS",
- "GRANITE_WALL",
- "GRASS_BLOCK",
- "GRAVEL",
- "GRAY_BANNER",
- "GRAY_BED",
- "GRAY_CANDLE",
- "GRAY_CANDLE_CAKE",
- "GRAY_CARPET",
- "GRAY_CONCRETE",
- "GRAY_CONCRETE_POWDER",
- "GRAY_DYE",
- "GRAY_GLAZED_TERRACOTTA",
- "GRAY_SHULKER_BOX",
- "GRAY_STAINED_GLASS",
- "GRAY_STAINED_GLASS_PANE",
- "GRAY_TERRACOTTA",
- "GRAY_WALL_BANNER",
- "GRAY_WOOL",
- "GREEN_BANNER",
- "GREEN_BED",
- "GREEN_CANDLE",
- "GREEN_CANDLE_CAKE",
- "GREEN_CARPET",
- "GREEN_CONCRETE",
- "GREEN_CONCRETE_POWDER",
- "GREEN_DYE",
- "GREEN_GLAZED_TERRACOTTA",
- "GREEN_SHULKER_BOX",
- "GREEN_STAINED_GLASS",
- "GREEN_STAINED_GLASS_PANE",
- "GREEN_TERRACOTTA",
- "GREEN_WALL_BANNER",
- "GREEN_WOOL",
- "GRINDSTONE",
- "GUARDIAN_SPAWN_EGG",
- "GUNPOWDER",
- "HANGING_ROOTS",
- "HAY_BLOCK",
- "HEART_OF_THE_SEA",
- "HEART_POTTERY_SHERD",
- "HEARTBREAK_POTTERY_SHERD",
- "HEAVY_WEIGHTED_PRESSURE_PLATE",
- "HOGLIN_SPAWN_EGG",
- "HONEY_BLOCK",
- "HONEY_BOTTLE",
- "HONEYCOMB",
- "HONEYCOMB_BLOCK",
- "HOPPER",
- "HOPPER_MINECART",
- "HORN_CORAL",
- "HORN_CORAL_BLOCK",
- "HORN_CORAL_FAN",
- "HORN_CORAL_WALL_FAN",
- "HORSE_SPAWN_EGG",
- "HOST_ARMOR_TRIM_SMITHING_TEMPLATE",
- "HOWL_POTTERY_SHERD",
- "HUSK_SPAWN_EGG",
- "ICE",
- "INFESTED_CHISELED_STONE_BRICKS",
- "INFESTED_COBBLESTONE",
- "INFESTED_CRACKED_STONE_BRICKS",
- "INFESTED_DEEPSLATE",
- "INFESTED_MOSSY_STONE_BRICKS",
- "INFESTED_STONE",
- "INFESTED_STONE_BRICKS",
- "INK_SAC",
- "IRON_AXE",
- "IRON_BARS",
- "IRON_BLOCK",
- "IRON_BOOTS",
- "IRON_CHESTPLATE",
- "IRON_DOOR",
- "IRON_GOLEM_SPAWN_EGG",
- "IRON_HELMET",
- "IRON_HOE",
- "IRON_HORSE_ARMOR",
- "IRON_INGOT",
- "IRON_LEGGINGS",
- "IRON_NUGGET",
- "IRON_ORE",
- "IRON_PICKAXE",
- "IRON_SHOVEL",
- "IRON_SWORD",
- "IRON_TRAPDOOR",
- "ITEM_FRAME",
- "JACK_O_LANTERN",
- "JIGSAW",
- "JUKEBOX",
- "JUNGLE_BOAT",
- "JUNGLE_BUTTON",
- "JUNGLE_CHEST_BOAT",
- "JUNGLE_DOOR",
- "JUNGLE_FENCE",
- "JUNGLE_FENCE_GATE",
- "JUNGLE_HANGING_SIGN",
- "JUNGLE_LEAVES",
- "JUNGLE_LOG",
- "JUNGLE_PLANKS",
- "JUNGLE_PRESSURE_PLATE",
- "JUNGLE_SAPLING",
- "JUNGLE_SIGN",
- "JUNGLE_SLAB",
- "JUNGLE_STAIRS",
- "JUNGLE_TRAPDOOR",
- "JUNGLE_WALL_HANGING_SIGN",
- "JUNGLE_WALL_SIGN",
- "JUNGLE_WOOD",
- "KELP",
- "KELP_PLANT",
- "KNOWLEDGE_BOOK",
- "LADDER",
- "LANTERN",
- "LAPIS_BLOCK",
- "LAPIS_LAZULI",
- "LAPIS_ORE",
- "LARGE_AMETHYST_BUD",
- "LARGE_FERN",
- "LAVA",
- "LAVA_BUCKET",
- "LAVA_CAULDRON",
- "LEAD",
- "LEATHER",
- "LEATHER_BOOTS",
- "LEATHER_CHESTPLATE",
- "LEATHER_HELMET",
- "LEATHER_HORSE_ARMOR",
- "LEATHER_LEGGINGS",
- "LECTERN",
- "LEGACY_ACACIA_DOOR",
- "LEGACY_ACACIA_DOOR_ITEM",
- "LEGACY_ACACIA_FENCE",
- "LEGACY_ACACIA_FENCE_GATE",
- "LEGACY_ACACIA_STAIRS",
- "LEGACY_ACTIVATOR_RAIL",
- "LEGACY_AIR",
- "LEGACY_ANVIL",
- "LEGACY_APPLE",
- "LEGACY_ARMOR_STAND",
- "LEGACY_ARROW",
- "LEGACY_BAKED_POTATO",
- "LEGACY_BANNER",
- "LEGACY_BARRIER",
- "LEGACY_BEACON",
- "LEGACY_BED",
- "LEGACY_BED_BLOCK",
- "LEGACY_BEDROCK",
- "LEGACY_BEETROOT",
- "LEGACY_BEETROOT_BLOCK",
- "LEGACY_BEETROOT_SEEDS",
- "LEGACY_BEETROOT_SOUP",
- "LEGACY_BIRCH_DOOR",
- "LEGACY_BIRCH_DOOR_ITEM",
- "LEGACY_BIRCH_FENCE",
- "LEGACY_BIRCH_FENCE_GATE",
- "LEGACY_BIRCH_WOOD_STAIRS",
- "LEGACY_BLACK_GLAZED_TERRACOTTA",
- "LEGACY_BLACK_SHULKER_BOX",
- "LEGACY_BLAZE_POWDER",
- "LEGACY_BLAZE_ROD",
- "LEGACY_BLUE_GLAZED_TERRACOTTA",
- "LEGACY_BLUE_SHULKER_BOX",
- "LEGACY_BOAT",
- "LEGACY_BOAT_ACACIA",
- "LEGACY_BOAT_BIRCH",
- "LEGACY_BOAT_DARK_OAK",
- "LEGACY_BOAT_JUNGLE",
- "LEGACY_BOAT_SPRUCE",
- "LEGACY_BONE",
- "LEGACY_BONE_BLOCK",
- "LEGACY_BOOK",
- "LEGACY_BOOK_AND_QUILL",
- "LEGACY_BOOKSHELF",
- "LEGACY_BOW",
- "LEGACY_BOWL",
- "LEGACY_BREAD",
- "LEGACY_BREWING_STAND",
- "LEGACY_BREWING_STAND_ITEM",
- "LEGACY_BRICK",
- "LEGACY_BRICK_STAIRS",
- "LEGACY_BROWN_GLAZED_TERRACOTTA",
- "LEGACY_BROWN_MUSHROOM",
- "LEGACY_BROWN_SHULKER_BOX",
- "LEGACY_BUCKET",
- "LEGACY_BURNING_FURNACE",
- "LEGACY_CACTUS",
- "LEGACY_CAKE",
- "LEGACY_CAKE_BLOCK",
- "LEGACY_CARPET",
- "LEGACY_CARROT",
- "LEGACY_CARROT_ITEM",
- "LEGACY_CARROT_STICK",
- "LEGACY_CAULDRON",
- "LEGACY_CAULDRON_ITEM",
- "LEGACY_CHAINMAIL_BOOTS",
- "LEGACY_CHAINMAIL_CHESTPLATE",
- "LEGACY_CHAINMAIL_HELMET",
- "LEGACY_CHAINMAIL_LEGGINGS",
- "LEGACY_CHEST",
- "LEGACY_CHORUS_FLOWER",
- "LEGACY_CHORUS_FRUIT",
- "LEGACY_CHORUS_FRUIT_POPPED",
- "LEGACY_CHORUS_PLANT",
- "LEGACY_CLAY",
- "LEGACY_CLAY_BALL",
- "LEGACY_CLAY_BRICK",
- "LEGACY_COAL",
- "LEGACY_COAL_BLOCK",
- "LEGACY_COAL_ORE",
- "LEGACY_COBBLE_WALL",
- "LEGACY_COBBLESTONE",
- "LEGACY_COBBLESTONE_STAIRS",
- "LEGACY_COCOA",
- "LEGACY_COMMAND",
- "LEGACY_COMMAND_CHAIN",
- "LEGACY_COMMAND_MINECART",
- "LEGACY_COMMAND_REPEATING",
- "LEGACY_COMPASS",
- "LEGACY_CONCRETE",
- "LEGACY_CONCRETE_POWDER",
- "LEGACY_COOKED_BEEF",
- "LEGACY_COOKED_CHICKEN",
- "LEGACY_COOKED_FISH",
- "LEGACY_COOKED_MUTTON",
- "LEGACY_COOKED_RABBIT",
- "LEGACY_COOKIE",
- "LEGACY_CROPS",
- "LEGACY_CYAN_GLAZED_TERRACOTTA",
- "LEGACY_CYAN_SHULKER_BOX",
- "LEGACY_DARK_OAK_DOOR",
- "LEGACY_DARK_OAK_DOOR_ITEM",
- "LEGACY_DARK_OAK_FENCE",
- "LEGACY_DARK_OAK_FENCE_GATE",
- "LEGACY_DARK_OAK_STAIRS",
- "LEGACY_DAYLIGHT_DETECTOR",
- "LEGACY_DAYLIGHT_DETECTOR_INVERTED",
- "LEGACY_DEAD_BUSH",
- "LEGACY_DETECTOR_RAIL",
- "LEGACY_DIAMOND",
- "LEGACY_DIAMOND_AXE",
- "LEGACY_DIAMOND_BARDING",
- "LEGACY_DIAMOND_BLOCK",
- "LEGACY_DIAMOND_BOOTS",
- "LEGACY_DIAMOND_CHESTPLATE",
- "LEGACY_DIAMOND_HELMET",
- "LEGACY_DIAMOND_HOE",
- "LEGACY_DIAMOND_LEGGINGS",
- "LEGACY_DIAMOND_ORE",
- "LEGACY_DIAMOND_PICKAXE",
- "LEGACY_DIAMOND_SPADE",
- "LEGACY_DIAMOND_SWORD",
- "LEGACY_DIODE",
- "LEGACY_DIODE_BLOCK_OFF",
- "LEGACY_DIODE_BLOCK_ON",
- "LEGACY_DIRT",
- "LEGACY_DISPENSER",
- "LEGACY_DOUBLE_PLANT",
- "LEGACY_DOUBLE_STEP",
- "LEGACY_DOUBLE_STONE_SLAB2",
- "LEGACY_DRAGON_EGG",
- "LEGACY_DRAGONS_BREATH",
- "LEGACY_DROPPER",
- "LEGACY_EGG",
- "LEGACY_ELYTRA",
- "LEGACY_EMERALD",
- "LEGACY_EMERALD_BLOCK",
- "LEGACY_EMERALD_ORE",
- "LEGACY_EMPTY_MAP",
- "LEGACY_ENCHANTED_BOOK",
- "LEGACY_ENCHANTMENT_TABLE",
- "LEGACY_END_BRICKS",
- "LEGACY_END_CRYSTAL",
- "LEGACY_END_GATEWAY",
- "LEGACY_END_ROD",
- "LEGACY_ENDER_CHEST",
- "LEGACY_ENDER_PEARL",
- "LEGACY_ENDER_PORTAL",
- "LEGACY_ENDER_PORTAL_FRAME",
- "LEGACY_ENDER_STONE",
- "LEGACY_EXP_BOTTLE",
- "LEGACY_EXPLOSIVE_MINECART",
- "LEGACY_EYE_OF_ENDER",
- "LEGACY_FEATHER",
- "LEGACY_FENCE",
- "LEGACY_FENCE_GATE",
- "LEGACY_FERMENTED_SPIDER_EYE",
- "LEGACY_FIRE",
- "LEGACY_FIREBALL",
- "LEGACY_FIREWORK",
- "LEGACY_FIREWORK_CHARGE",
- "LEGACY_FISHING_ROD",
- "LEGACY_FLINT",
- "LEGACY_FLINT_AND_STEEL",
- "LEGACY_FLOWER_POT",
- "LEGACY_FLOWER_POT_ITEM",
- "LEGACY_FROSTED_ICE",
- "LEGACY_FURNACE",
- "LEGACY_GHAST_TEAR",
- "LEGACY_GLASS",
- "LEGACY_GLASS_BOTTLE",
- "LEGACY_GLOWING_REDSTONE_ORE",
- "LEGACY_GLOWSTONE",
- "LEGACY_GLOWSTONE_DUST",
- "LEGACY_GOLD_AXE",
- "LEGACY_GOLD_BARDING",
- "LEGACY_GOLD_BLOCK",
- "LEGACY_GOLD_BOOTS",
- "LEGACY_GOLD_CHESTPLATE",
- "LEGACY_GOLD_HELMET",
- "LEGACY_GOLD_HOE",
- "LEGACY_GOLD_INGOT",
- "LEGACY_GOLD_LEGGINGS",
- "LEGACY_GOLD_NUGGET",
- "LEGACY_GOLD_ORE",
- "LEGACY_GOLD_PICKAXE",
- "LEGACY_GOLD_PLATE",
- "LEGACY_GOLD_RECORD",
- "LEGACY_GOLD_SPADE",
- "LEGACY_GOLD_SWORD",
- "LEGACY_GOLDEN_APPLE",
- "LEGACY_GOLDEN_CARROT",
- "LEGACY_GRASS",
- "LEGACY_GRASS_PATH",
- "LEGACY_GRAVEL",
- "LEGACY_GRAY_GLAZED_TERRACOTTA",
- "LEGACY_GRAY_SHULKER_BOX",
- "LEGACY_GREEN_GLAZED_TERRACOTTA",
- "LEGACY_GREEN_RECORD",
- "LEGACY_GREEN_SHULKER_BOX",
- "LEGACY_GRILLED_PORK",
- "LEGACY_HARD_CLAY",
- "LEGACY_HAY_BLOCK",
- "LEGACY_HOPPER",
- "LEGACY_HOPPER_MINECART",
- "LEGACY_HUGE_MUSHROOM_1",
- "LEGACY_HUGE_MUSHROOM_2",
- "LEGACY_ICE",
- "LEGACY_INK_SACK",
- "LEGACY_IRON_AXE",
- "LEGACY_IRON_BARDING",
- "LEGACY_IRON_BLOCK",
- "LEGACY_IRON_BOOTS",
- "LEGACY_IRON_CHESTPLATE",
- "LEGACY_IRON_DOOR",
- "LEGACY_IRON_DOOR_BLOCK",
- "LEGACY_IRON_FENCE",
- "LEGACY_IRON_HELMET",
- "LEGACY_IRON_HOE",
- "LEGACY_IRON_INGOT",
- "LEGACY_IRON_LEGGINGS",
- "LEGACY_IRON_NUGGET",
- "LEGACY_IRON_ORE",
- "LEGACY_IRON_PICKAXE",
- "LEGACY_IRON_PLATE",
- "LEGACY_IRON_SPADE",
- "LEGACY_IRON_SWORD",
- "LEGACY_IRON_TRAPDOOR",
- "LEGACY_ITEM_FRAME",
- "LEGACY_JACK_O_LANTERN",
- "LEGACY_JUKEBOX",
- "LEGACY_JUNGLE_DOOR",
- "LEGACY_JUNGLE_DOOR_ITEM",
- "LEGACY_JUNGLE_FENCE",
- "LEGACY_JUNGLE_FENCE_GATE",
- "LEGACY_JUNGLE_WOOD_STAIRS",
- "LEGACY_KNOWLEDGE_BOOK",
- "LEGACY_LADDER",
- "LEGACY_LAPIS_BLOCK",
- "LEGACY_LAPIS_ORE",
- "LEGACY_LAVA",
- "LEGACY_LAVA_BUCKET",
- "LEGACY_LEASH",
- "LEGACY_LEATHER",
- "LEGACY_LEATHER_BOOTS",
- "LEGACY_LEATHER_CHESTPLATE",
- "LEGACY_LEATHER_HELMET",
- "LEGACY_LEATHER_LEGGINGS",
- "LEGACY_LEAVES",
- "LEGACY_LEAVES_2",
- "LEGACY_LEVER",
- "LEGACY_LIGHT_BLUE_GLAZED_TERRACOTTA",
- "LEGACY_LIGHT_BLUE_SHULKER_BOX",
- "LEGACY_LIME_GLAZED_TERRACOTTA",
- "LEGACY_LIME_SHULKER_BOX",
- "LEGACY_LINGERING_POTION",
- "LEGACY_LOG",
- "LEGACY_LOG_2",
- "LEGACY_LONG_GRASS",
- "LEGACY_MAGENTA_GLAZED_TERRACOTTA",
- "LEGACY_MAGENTA_SHULKER_BOX",
- "LEGACY_MAGMA",
- "LEGACY_MAGMA_CREAM",
- "LEGACY_MAP",
- "LEGACY_MELON",
- "LEGACY_MELON_BLOCK",
- "LEGACY_MELON_SEEDS",
- "LEGACY_MELON_STEM",
- "LEGACY_MILK_BUCKET",
- "LEGACY_MINECART",
- "LEGACY_MOB_SPAWNER",
- "LEGACY_MONSTER_EGG",
- "LEGACY_MONSTER_EGGS",
- "LEGACY_MOSSY_COBBLESTONE",
- "LEGACY_MUSHROOM_SOUP",
- "LEGACY_MUTTON",
- "LEGACY_MYCEL",
- "LEGACY_NAME_TAG",
- "LEGACY_NETHER_BRICK",
- "LEGACY_NETHER_BRICK_ITEM",
- "LEGACY_NETHER_BRICK_STAIRS",
- "LEGACY_NETHER_FENCE",
- "LEGACY_NETHER_STALK",
- "LEGACY_NETHER_STAR",
- "LEGACY_NETHER_WART_BLOCK",
- "LEGACY_NETHER_WARTS",
- "LEGACY_NETHERRACK",
- "LEGACY_NOTE_BLOCK",
- "LEGACY_OBSERVER",
- "LEGACY_OBSIDIAN",
- "LEGACY_ORANGE_GLAZED_TERRACOTTA",
- "LEGACY_ORANGE_SHULKER_BOX",
- "LEGACY_PACKED_ICE",
- "LEGACY_PAINTING",
- "LEGACY_PAPER",
- "LEGACY_PINK_GLAZED_TERRACOTTA",
- "LEGACY_PINK_SHULKER_BOX",
- "LEGACY_PISTON_BASE",
- "LEGACY_PISTON_EXTENSION",
- "LEGACY_PISTON_MOVING_PIECE",
- "LEGACY_PISTON_STICKY_BASE",
- "LEGACY_POISONOUS_POTATO",
- "LEGACY_PORK",
- "LEGACY_PORTAL",
- "LEGACY_POTATO",
- "LEGACY_POTATO_ITEM",
- "LEGACY_POTION",
- "LEGACY_POWERED_MINECART",
- "LEGACY_POWERED_RAIL",
- "LEGACY_PRISMARINE",
- "LEGACY_PRISMARINE_CRYSTALS",
- "LEGACY_PRISMARINE_SHARD",
- "LEGACY_PUMPKIN",
- "LEGACY_PUMPKIN_PIE",
- "LEGACY_PUMPKIN_SEEDS",
- "LEGACY_PUMPKIN_STEM",
- "LEGACY_PURPLE_GLAZED_TERRACOTTA",
- "LEGACY_PURPLE_SHULKER_BOX",
- "LEGACY_PURPUR_BLOCK",
- "LEGACY_PURPUR_DOUBLE_SLAB",
- "LEGACY_PURPUR_PILLAR",
- "LEGACY_PURPUR_SLAB",
- "LEGACY_PURPUR_STAIRS",
- "LEGACY_QUARTZ",
- "LEGACY_QUARTZ_BLOCK",
- "LEGACY_QUARTZ_ORE",
- "LEGACY_QUARTZ_STAIRS",
- "LEGACY_RABBIT",
- "LEGACY_RABBIT_FOOT",
- "LEGACY_RABBIT_HIDE",
- "LEGACY_RABBIT_STEW",
- "LEGACY_RAILS",
- "LEGACY_RAW_BEEF",
- "LEGACY_RAW_CHICKEN",
- "LEGACY_RAW_FISH",
- "LEGACY_RECORD_10",
- "LEGACY_RECORD_11",
- "LEGACY_RECORD_12",
- "LEGACY_RECORD_3",
- "LEGACY_RECORD_4",
- "LEGACY_RECORD_5",
- "LEGACY_RECORD_6",
- "LEGACY_RECORD_7",
- "LEGACY_RECORD_8",
- "LEGACY_RECORD_9",
- "LEGACY_RED_GLAZED_TERRACOTTA",
- "LEGACY_RED_MUSHROOM",
- "LEGACY_RED_NETHER_BRICK",
- "LEGACY_RED_ROSE",
- "LEGACY_RED_SANDSTONE",
- "LEGACY_RED_SANDSTONE_STAIRS",
- "LEGACY_RED_SHULKER_BOX",
- "LEGACY_REDSTONE",
- "LEGACY_REDSTONE_BLOCK",
- "LEGACY_REDSTONE_COMPARATOR",
- "LEGACY_REDSTONE_COMPARATOR_OFF",
- "LEGACY_REDSTONE_COMPARATOR_ON",
- "LEGACY_REDSTONE_LAMP_OFF",
- "LEGACY_REDSTONE_LAMP_ON",
- "LEGACY_REDSTONE_ORE",
- "LEGACY_REDSTONE_TORCH_OFF",
- "LEGACY_REDSTONE_TORCH_ON",
- "LEGACY_REDSTONE_WIRE",
- "LEGACY_ROTTEN_FLESH",
- "LEGACY_SADDLE",
- "LEGACY_SAND",
- "LEGACY_SANDSTONE",
- "LEGACY_SANDSTONE_STAIRS",
- "LEGACY_SAPLING",
- "LEGACY_SEA_LANTERN",
- "LEGACY_SEEDS",
- "LEGACY_SHEARS",
- "LEGACY_SHIELD",
- "LEGACY_SHULKER_SHELL",
- "LEGACY_SIGN",
- "LEGACY_SIGN_POST",
- "LEGACY_SILVER_GLAZED_TERRACOTTA",
- "LEGACY_SILVER_SHULKER_BOX",
- "LEGACY_SKULL",
- "LEGACY_SKULL_ITEM",
- "LEGACY_SLIME_BALL",
- "LEGACY_SLIME_BLOCK",
- "LEGACY_SMOOTH_BRICK",
- "LEGACY_SMOOTH_STAIRS",
- "LEGACY_SNOW",
- "LEGACY_SNOW_BALL",
- "LEGACY_SNOW_BLOCK",
- "LEGACY_SOIL",
- "LEGACY_SOUL_SAND",
- "LEGACY_SPECKLED_MELON",
- "LEGACY_SPECTRAL_ARROW",
- "LEGACY_SPIDER_EYE",
- "LEGACY_SPLASH_POTION",
- "LEGACY_SPONGE",
- "LEGACY_SPRUCE_DOOR",
- "LEGACY_SPRUCE_DOOR_ITEM",
- "LEGACY_SPRUCE_FENCE",
- "LEGACY_SPRUCE_FENCE_GATE",
- "LEGACY_SPRUCE_WOOD_STAIRS",
- "LEGACY_STAINED_CLAY",
- "LEGACY_STAINED_GLASS",
- "LEGACY_STAINED_GLASS_PANE",
- "LEGACY_STANDING_BANNER",
- "LEGACY_STATIONARY_LAVA",
- "LEGACY_STATIONARY_WATER",
- "LEGACY_STEP",
- "LEGACY_STICK",
- "LEGACY_STONE",
- "LEGACY_STONE_AXE",
- "LEGACY_STONE_BUTTON",
- "LEGACY_STONE_HOE",
- "LEGACY_STONE_PICKAXE",
- "LEGACY_STONE_PLATE",
- "LEGACY_STONE_SLAB2",
- "LEGACY_STONE_SPADE",
- "LEGACY_STONE_SWORD",
- "LEGACY_STORAGE_MINECART",
- "LEGACY_STRING",
- "LEGACY_STRUCTURE_BLOCK",
- "LEGACY_STRUCTURE_VOID",
- "LEGACY_SUGAR",
- "LEGACY_SUGAR_CANE",
- "LEGACY_SUGAR_CANE_BLOCK",
- "LEGACY_SULPHUR",
- "LEGACY_THIN_GLASS",
- "LEGACY_TIPPED_ARROW",
- "LEGACY_TNT",
- "LEGACY_TORCH",
- "LEGACY_TOTEM",
- "LEGACY_TRAP_DOOR",
- "LEGACY_TRAPPED_CHEST",
- "LEGACY_TRIPWIRE",
- "LEGACY_TRIPWIRE_HOOK",
- "LEGACY_VINE",
- "LEGACY_WALL_BANNER",
- "LEGACY_WALL_SIGN",
- "LEGACY_WATCH",
- "LEGACY_WATER",
- "LEGACY_WATER_BUCKET",
- "LEGACY_WATER_LILY",
- "LEGACY_WEB",
- "LEGACY_WHEAT",
- "LEGACY_WHITE_GLAZED_TERRACOTTA",
- "LEGACY_WHITE_SHULKER_BOX",
- "LEGACY_WOOD",
- "LEGACY_WOOD_AXE",
- "LEGACY_WOOD_BUTTON",
- "LEGACY_WOOD_DOOR",
- "LEGACY_WOOD_DOUBLE_STEP",
- "LEGACY_WOOD_HOE",
- "LEGACY_WOOD_PICKAXE",
- "LEGACY_WOOD_PLATE",
- "LEGACY_WOOD_SPADE",
- "LEGACY_WOOD_STAIRS",
- "LEGACY_WOOD_STEP",
- "LEGACY_WOOD_SWORD",
- "LEGACY_WOODEN_DOOR",
- "LEGACY_WOOL",
- "LEGACY_WORKBENCH",
- "LEGACY_WRITTEN_BOOK",
- "LEGACY_YELLOW_FLOWER",
- "LEGACY_YELLOW_GLAZED_TERRACOTTA",
- "LEGACY_YELLOW_SHULKER_BOX",
- "LEVER",
- "LIGHT",
- "LIGHT_BLUE_BANNER",
- "LIGHT_BLUE_BED",
- "LIGHT_BLUE_CANDLE",
- "LIGHT_BLUE_CANDLE_CAKE",
- "LIGHT_BLUE_CARPET",
- "LIGHT_BLUE_CONCRETE",
- "LIGHT_BLUE_CONCRETE_POWDER",
- "LIGHT_BLUE_DYE",
- "LIGHT_BLUE_GLAZED_TERRACOTTA",
- "LIGHT_BLUE_SHULKER_BOX",
- "LIGHT_BLUE_STAINED_GLASS",
- "LIGHT_BLUE_STAINED_GLASS_PANE",
- "LIGHT_BLUE_TERRACOTTA",
- "LIGHT_BLUE_WALL_BANNER",
- "LIGHT_BLUE_WOOL",
- "LIGHT_GRAY_BANNER",
- "LIGHT_GRAY_BED",
- "LIGHT_GRAY_CANDLE",
- "LIGHT_GRAY_CANDLE_CAKE",
- "LIGHT_GRAY_CARPET",
- "LIGHT_GRAY_CONCRETE",
- "LIGHT_GRAY_CONCRETE_POWDER",
- "LIGHT_GRAY_DYE",
- "LIGHT_GRAY_GLAZED_TERRACOTTA",
- "LIGHT_GRAY_SHULKER_BOX",
- "LIGHT_GRAY_STAINED_GLASS",
- "LIGHT_GRAY_STAINED_GLASS_PANE",
- "LIGHT_GRAY_TERRACOTTA",
- "LIGHT_GRAY_WALL_BANNER",
- "LIGHT_GRAY_WOOL",
- "LIGHT_WEIGHTED_PRESSURE_PLATE",
- "LIGHTNING_ROD",
- "LILAC",
- "LILY_OF_THE_VALLEY",
- "LILY_PAD",
- "LIME_BANNER",
- "LIME_BED",
- "LIME_CANDLE",
- "LIME_CANDLE_CAKE",
- "LIME_CARPET",
- "LIME_CONCRETE",
- "LIME_CONCRETE_POWDER",
- "LIME_DYE",
- "LIME_GLAZED_TERRACOTTA",
- "LIME_SHULKER_BOX",
- "LIME_STAINED_GLASS",
- "LIME_STAINED_GLASS_PANE",
- "LIME_TERRACOTTA",
- "LIME_WALL_BANNER",
- "LIME_WOOL",
- "LINGERING_POTION",
- "LLAMA_SPAWN_EGG",
- "LODESTONE",
- "LOOM",
- "MAGENTA_BANNER",
- "MAGENTA_BED",
- "MAGENTA_CANDLE",
- "MAGENTA_CANDLE_CAKE",
- "MAGENTA_CARPET",
- "MAGENTA_CONCRETE",
- "MAGENTA_CONCRETE_POWDER",
- "MAGENTA_DYE",
- "MAGENTA_GLAZED_TERRACOTTA",
- "MAGENTA_SHULKER_BOX",
- "MAGENTA_STAINED_GLASS",
- "MAGENTA_STAINED_GLASS_PANE",
- "MAGENTA_TERRACOTTA",
- "MAGENTA_WALL_BANNER",
- "MAGENTA_WOOL",
- "MAGMA_BLOCK",
- "MAGMA_CREAM",
- "MAGMA_CUBE_SPAWN_EGG",
- "MANGROVE_BOAT",
- "MANGROVE_BUTTON",
- "MANGROVE_CHEST_BOAT",
- "MANGROVE_DOOR",
- "MANGROVE_FENCE",
- "MANGROVE_FENCE_GATE",
- "MANGROVE_HANGING_SIGN",
- "MANGROVE_LEAVES",
- "MANGROVE_LOG",
- "MANGROVE_PLANKS",
- "MANGROVE_PRESSURE_PLATE",
- "MANGROVE_PROPAGULE",
- "MANGROVE_ROOTS",
- "MANGROVE_SIGN",
- "MANGROVE_SLAB",
- "MANGROVE_STAIRS",
- "MANGROVE_TRAPDOOR",
- "MANGROVE_WALL_HANGING_SIGN",
- "MANGROVE_WALL_SIGN",
- "MANGROVE_WOOD",
- "MAP",
- "MEDIUM_AMETHYST_BUD",
- "MELON",
- "MELON_SEEDS",
- "MELON_SLICE",
- "MELON_STEM",
- "MILK_BUCKET",
- "MINECART",
- "MINER_POTTERY_SHERD",
- "MOJANG_BANNER_PATTERN",
- "MOOSHROOM_SPAWN_EGG",
- "MOSS_BLOCK",
- "MOSS_CARPET",
- "MOSSY_COBBLESTONE",
- "MOSSY_COBBLESTONE_SLAB",
- "MOSSY_COBBLESTONE_STAIRS",
- "MOSSY_COBBLESTONE_WALL",
- "MOSSY_STONE_BRICK_SLAB",
- "MOSSY_STONE_BRICK_STAIRS",
- "MOSSY_STONE_BRICK_WALL",
- "MOSSY_STONE_BRICKS",
- "MOURNER_POTTERY_SHERD",
- "MOVING_PISTON",
- "MUD",
- "MUD_BRICK_SLAB",
- "MUD_BRICK_STAIRS",
- "MUD_BRICK_WALL",
- "MUD_BRICKS",
- "MUDDY_MANGROVE_ROOTS",
- "MULE_SPAWN_EGG",
- "MUSHROOM_STEM",
- "MUSHROOM_STEW",
- "MUSIC_DISC_11",
- "MUSIC_DISC_13",
- "MUSIC_DISC_5",
- "MUSIC_DISC_BLOCKS",
- "MUSIC_DISC_CAT",
- "MUSIC_DISC_CHIRP",
- "MUSIC_DISC_FAR",
- "MUSIC_DISC_MALL",
- "MUSIC_DISC_MELLOHI",
- "MUSIC_DISC_OTHERSIDE",
- "MUSIC_DISC_PIGSTEP",
- "MUSIC_DISC_RELIC",
- "MUSIC_DISC_STAL",
- "MUSIC_DISC_STRAD",
- "MUSIC_DISC_WAIT",
- "MUSIC_DISC_WARD",
- "MUTTON",
- "MYCELIUM",
- "NAME_TAG",
- "NAUTILUS_SHELL",
- "NETHER_BRICK",
- "NETHER_BRICK_FENCE",
- "NETHER_BRICK_SLAB",
- "NETHER_BRICK_STAIRS",
- "NETHER_BRICK_WALL",
- "NETHER_BRICKS",
- "NETHER_GOLD_ORE",
- "NETHER_PORTAL",
- "NETHER_QUARTZ_ORE",
- "NETHER_SPROUTS",
- "NETHER_STAR",
- "NETHER_WART",
- "NETHER_WART_BLOCK",
- "NETHERITE_AXE",
- "NETHERITE_BLOCK",
- "NETHERITE_BOOTS",
- "NETHERITE_CHESTPLATE",
- "NETHERITE_HELMET",
- "NETHERITE_HOE",
- "NETHERITE_INGOT",
- "NETHERITE_LEGGINGS",
- "NETHERITE_PICKAXE",
- "NETHERITE_SCRAP",
- "NETHERITE_SHOVEL",
- "NETHERITE_SWORD",
- "NETHERITE_UPGRADE_SMITHING_TEMPLATE",
- "NETHERRACK",
- "NOTE_BLOCK",
- "OAK_BOAT",
- "OAK_BUTTON",
- "OAK_CHEST_BOAT",
- "OAK_DOOR",
- "OAK_FENCE",
- "OAK_FENCE_GATE",
- "OAK_HANGING_SIGN",
- "OAK_LEAVES",
- "OAK_LOG",
- "OAK_PLANKS",
- "OAK_PRESSURE_PLATE",
- "OAK_SAPLING",
- "OAK_SIGN",
- "OAK_SLAB",
- "OAK_STAIRS",
- "OAK_TRAPDOOR",
- "OAK_WALL_HANGING_SIGN",
- "OAK_WALL_SIGN",
- "OAK_WOOD",
- "OBSERVER",
- "OBSIDIAN",
- "OCELOT_SPAWN_EGG",
- "OCHRE_FROGLIGHT",
- "ORANGE_BANNER",
- "ORANGE_BED",
- "ORANGE_CANDLE",
- "ORANGE_CANDLE_CAKE",
- "ORANGE_CARPET",
- "ORANGE_CONCRETE",
- "ORANGE_CONCRETE_POWDER",
- "ORANGE_DYE",
- "ORANGE_GLAZED_TERRACOTTA",
- "ORANGE_SHULKER_BOX",
- "ORANGE_STAINED_GLASS",
- "ORANGE_STAINED_GLASS_PANE",
- "ORANGE_TERRACOTTA",
- "ORANGE_TULIP",
- "ORANGE_WALL_BANNER",
- "ORANGE_WOOL",
- "OXEYE_DAISY",
- "OXIDIZED_CHISELED_COPPER",
- "OXIDIZED_COPPER",
- "OXIDIZED_COPPER_BULB",
- "OXIDIZED_COPPER_DOOR",
- "OXIDIZED_COPPER_GRATE",
- "OXIDIZED_COPPER_TRAPDOOR",
- "OXIDIZED_CUT_COPPER",
- "OXIDIZED_CUT_COPPER_SLAB",
- "OXIDIZED_CUT_COPPER_STAIRS",
- "PACKED_ICE",
- "PACKED_MUD",
- "PAINTING",
- "PANDA_SPAWN_EGG",
- "PAPER",
- "PARROT_SPAWN_EGG",
- "PEARLESCENT_FROGLIGHT",
- "PEONY",
- "PETRIFIED_OAK_SLAB",
- "PHANTOM_MEMBRANE",
- "PHANTOM_SPAWN_EGG",
- "PIG_SPAWN_EGG",
- "PIGLIN_BANNER_PATTERN",
- "PIGLIN_BRUTE_SPAWN_EGG",
- "PIGLIN_HEAD",
- "PIGLIN_SPAWN_EGG",
- "PIGLIN_WALL_HEAD",
- "PILLAGER_SPAWN_EGG",
- "PINK_BANNER",
- "PINK_BED",
- "PINK_CANDLE",
- "PINK_CANDLE_CAKE",
- "PINK_CARPET",
- "PINK_CONCRETE",
- "PINK_CONCRETE_POWDER",
- "PINK_DYE",
- "PINK_GLAZED_TERRACOTTA",
- "PINK_PETALS",
- "PINK_SHULKER_BOX",
- "PINK_STAINED_GLASS",
- "PINK_STAINED_GLASS_PANE",
- "PINK_TERRACOTTA",
- "PINK_TULIP",
- "PINK_WALL_BANNER",
- "PINK_WOOL",
- "PISTON",
- "PISTON_HEAD",
- "PITCHER_CROP",
- "PITCHER_PLANT",
- "PITCHER_POD",
- "PLAYER_HEAD",
- "PLAYER_WALL_HEAD",
- "PLENTY_POTTERY_SHERD",
- "PODZOL",
- "POINTED_DRIPSTONE",
- "POISONOUS_POTATO",
- "POLAR_BEAR_SPAWN_EGG",
- "POLISHED_ANDESITE",
- "POLISHED_ANDESITE_SLAB",
- "POLISHED_ANDESITE_STAIRS",
- "POLISHED_BASALT",
- "POLISHED_BLACKSTONE",
- "POLISHED_BLACKSTONE_BRICK_SLAB",
- "POLISHED_BLACKSTONE_BRICK_STAIRS",
- "POLISHED_BLACKSTONE_BRICK_WALL",
- "POLISHED_BLACKSTONE_BRICKS",
- "POLISHED_BLACKSTONE_BUTTON",
- "POLISHED_BLACKSTONE_PRESSURE_PLATE",
- "POLISHED_BLACKSTONE_SLAB",
- "POLISHED_BLACKSTONE_STAIRS",
- "POLISHED_BLACKSTONE_WALL",
- "POLISHED_DEEPSLATE",
- "POLISHED_DEEPSLATE_SLAB",
- "POLISHED_DEEPSLATE_STAIRS",
- "POLISHED_DEEPSLATE_WALL",
- "POLISHED_DIORITE",
- "POLISHED_DIORITE_SLAB",
- "POLISHED_DIORITE_STAIRS",
- "POLISHED_GRANITE",
- "POLISHED_GRANITE_SLAB",
- "POLISHED_GRANITE_STAIRS",
- "POLISHED_TUFF",
- "POLISHED_TUFF_SLAB",
- "POLISHED_TUFF_STAIRS",
- "POLISHED_TUFF_WALL",
- "POPPED_CHORUS_FRUIT",
- "POPPY",
- "PORKCHOP",
- "POTATO",
- "POTATOES",
- "POTION",
- "POTTED_ACACIA_SAPLING",
- "POTTED_ALLIUM",
- "POTTED_AZALEA_BUSH",
- "POTTED_AZURE_BLUET",
- "POTTED_BAMBOO",
- "POTTED_BIRCH_SAPLING",
- "POTTED_BLUE_ORCHID",
- "POTTED_BROWN_MUSHROOM",
- "POTTED_CACTUS",
- "POTTED_CHERRY_SAPLING",
- "POTTED_CORNFLOWER",
- "POTTED_CRIMSON_FUNGUS",
- "POTTED_CRIMSON_ROOTS",
- "POTTED_DANDELION",
- "POTTED_DARK_OAK_SAPLING",
- "POTTED_DEAD_BUSH",
- "POTTED_FERN",
- "POTTED_FLOWERING_AZALEA_BUSH",
- "POTTED_JUNGLE_SAPLING",
- "POTTED_LILY_OF_THE_VALLEY",
- "POTTED_MANGROVE_PROPAGULE",
- "POTTED_OAK_SAPLING",
- "POTTED_ORANGE_TULIP",
- "POTTED_OXEYE_DAISY",
- "POTTED_PINK_TULIP",
- "POTTED_POPPY",
- "POTTED_RED_MUSHROOM",
- "POTTED_RED_TULIP",
- "POTTED_SPRUCE_SAPLING",
- "POTTED_TORCHFLOWER",
- "POTTED_WARPED_FUNGUS",
- "POTTED_WARPED_ROOTS",
- "POTTED_WHITE_TULIP",
- "POTTED_WITHER_ROSE",
- "POWDER_SNOW",
- "POWDER_SNOW_BUCKET",
- "POWDER_SNOW_CAULDRON",
- "POWERED_RAIL",
- "PRISMARINE",
- "PRISMARINE_BRICK_SLAB",
- "PRISMARINE_BRICK_STAIRS",
- "PRISMARINE_BRICKS",
- "PRISMARINE_CRYSTALS",
- "PRISMARINE_SHARD",
- "PRISMARINE_SLAB",
- "PRISMARINE_STAIRS",
- "PRISMARINE_WALL",
- "PRIZE_POTTERY_SHERD",
- "PUFFERFISH",
- "PUFFERFISH_BUCKET",
- "PUFFERFISH_SPAWN_EGG",
- "PUMPKIN",
- "PUMPKIN_PIE",
- "PUMPKIN_SEEDS",
- "PUMPKIN_STEM",
- "PURPLE_BANNER",
- "PURPLE_BED",
- "PURPLE_CANDLE",
- "PURPLE_CANDLE_CAKE",
- "PURPLE_CARPET",
- "PURPLE_CONCRETE",
- "PURPLE_CONCRETE_POWDER",
- "PURPLE_DYE",
- "PURPLE_GLAZED_TERRACOTTA",
- "PURPLE_SHULKER_BOX",
- "PURPLE_STAINED_GLASS",
- "PURPLE_STAINED_GLASS_PANE",
- "PURPLE_TERRACOTTA",
- "PURPLE_WALL_BANNER",
- "PURPLE_WOOL",
- "PURPUR_BLOCK",
- "PURPUR_PILLAR",
- "PURPUR_SLAB",
- "PURPUR_STAIRS",
- "QUARTZ",
- "QUARTZ_BLOCK",
- "QUARTZ_BRICKS",
- "QUARTZ_PILLAR",
- "QUARTZ_SLAB",
- "QUARTZ_STAIRS",
- "RABBIT",
- "RABBIT_FOOT",
- "RABBIT_HIDE",
- "RABBIT_SPAWN_EGG",
- "RABBIT_STEW",
- "RAIL",
- "RAISER_ARMOR_TRIM_SMITHING_TEMPLATE",
- "RAVAGER_SPAWN_EGG",
- "RAW_COPPER",
- "RAW_COPPER_BLOCK",
- "RAW_GOLD",
- "RAW_GOLD_BLOCK",
- "RAW_IRON",
- "RAW_IRON_BLOCK",
- "RECOVERY_COMPASS",
- "RED_BANNER",
- "RED_BED",
- "RED_CANDLE",
- "RED_CANDLE_CAKE",
- "RED_CARPET",
- "RED_CONCRETE",
- "RED_CONCRETE_POWDER",
- "RED_DYE",
- "RED_GLAZED_TERRACOTTA",
- "RED_MUSHROOM",
- "RED_MUSHROOM_BLOCK",
- "RED_NETHER_BRICK_SLAB",
- "RED_NETHER_BRICK_STAIRS",
- "RED_NETHER_BRICK_WALL",
- "RED_NETHER_BRICKS",
- "RED_SAND",
- "RED_SANDSTONE",
- "RED_SANDSTONE_SLAB",
- "RED_SANDSTONE_STAIRS",
- "RED_SANDSTONE_WALL",
- "RED_SHULKER_BOX",
- "RED_STAINED_GLASS",
- "RED_STAINED_GLASS_PANE",
- "RED_TERRACOTTA",
- "RED_TULIP",
- "RED_WALL_BANNER",
- "RED_WOOL",
- "REDSTONE",
- "REDSTONE_BLOCK",
- "REDSTONE_LAMP",
- "REDSTONE_ORE",
- "REDSTONE_TORCH",
- "REDSTONE_WALL_TORCH",
- "REDSTONE_WIRE",
- "REINFORCED_DEEPSLATE",
- "REPEATER",
- "REPEATING_COMMAND_BLOCK",
- "RESPAWN_ANCHOR",
- "RIB_ARMOR_TRIM_SMITHING_TEMPLATE",
- "ROOTED_DIRT",
- "ROSE_BUSH",
- "ROTTEN_FLESH",
- "SADDLE",
- "SALMON",
- "SALMON_BUCKET",
- "SALMON_SPAWN_EGG",
- "SAND",
- "SANDSTONE",
- "SANDSTONE_SLAB",
- "SANDSTONE_STAIRS",
- "SANDSTONE_WALL",
- "SCAFFOLDING",
- "SCULK",
- "SCULK_CATALYST",
- "SCULK_SENSOR",
- "SCULK_SHRIEKER",
- "SCULK_VEIN",
- "SCUTE",
- "SEA_LANTERN",
- "SEA_PICKLE",
- "SEAGRASS",
- "SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE",
- "SHAPER_ARMOR_TRIM_SMITHING_TEMPLATE",
- "SHEAF_POTTERY_SHERD",
- "SHEARS",
- "SHEEP_SPAWN_EGG",
- "SHELTER_POTTERY_SHERD",
- "SHIELD",
- "SHORT_GRASS",
- "SHROOMLIGHT",
- "SHULKER_BOX",
- "SHULKER_SHELL",
- "SHULKER_SPAWN_EGG",
- "SILENCE_ARMOR_TRIM_SMITHING_TEMPLATE",
- "SILVERFISH_SPAWN_EGG",
- "SKELETON_HORSE_SPAWN_EGG",
- "SKELETON_SKULL",
- "SKELETON_SPAWN_EGG",
- "SKELETON_WALL_SKULL",
- "SKULL_BANNER_PATTERN",
- "SKULL_POTTERY_SHERD",
- "SLIME_BALL",
- "SLIME_BLOCK",
- "SLIME_SPAWN_EGG",
- "SMALL_AMETHYST_BUD",
- "SMALL_DRIPLEAF",
- "SMITHING_TABLE",
- "SMOKER",
- "SMOOTH_BASALT",
- "SMOOTH_QUARTZ",
- "SMOOTH_QUARTZ_SLAB",
- "SMOOTH_QUARTZ_STAIRS",
- "SMOOTH_RED_SANDSTONE",
- "SMOOTH_RED_SANDSTONE_SLAB",
- "SMOOTH_RED_SANDSTONE_STAIRS",
- "SMOOTH_SANDSTONE",
- "SMOOTH_SANDSTONE_SLAB",
- "SMOOTH_SANDSTONE_STAIRS",
- "SMOOTH_STONE",
- "SMOOTH_STONE_SLAB",
- "SNIFFER_EGG",
- "SNIFFER_SPAWN_EGG",
- "SNORT_POTTERY_SHERD",
- "SNOUT_ARMOR_TRIM_SMITHING_TEMPLATE",
- "SNOW",
- "SNOW_BLOCK",
- "SNOW_GOLEM_SPAWN_EGG",
- "SNOWBALL",
- "SOUL_CAMPFIRE",
- "SOUL_FIRE",
- "SOUL_LANTERN",
- "SOUL_SAND",
- "SOUL_SOIL",
- "SOUL_TORCH",
- "SOUL_WALL_TORCH",
- "SPAWNER",
- "SPECTRAL_ARROW",
- "SPIDER_EYE",
- "SPIDER_SPAWN_EGG",
- "SPIRE_ARMOR_TRIM_SMITHING_TEMPLATE",
- "SPLASH_POTION",
- "SPONGE",
- "SPORE_BLOSSOM",
- "SPRUCE_BOAT",
- "SPRUCE_BUTTON",
- "SPRUCE_CHEST_BOAT",
- "SPRUCE_DOOR",
- "SPRUCE_FENCE",
- "SPRUCE_FENCE_GATE",
- "SPRUCE_HANGING_SIGN",
- "SPRUCE_LEAVES",
- "SPRUCE_LOG",
- "SPRUCE_PLANKS",
- "SPRUCE_PRESSURE_PLATE",
- "SPRUCE_SAPLING",
- "SPRUCE_SIGN",
- "SPRUCE_SLAB",
- "SPRUCE_STAIRS",
- "SPRUCE_TRAPDOOR",
- "SPRUCE_WALL_HANGING_SIGN",
- "SPRUCE_WALL_SIGN",
- "SPRUCE_WOOD",
- "SPYGLASS",
- "SQUID_SPAWN_EGG",
- "STICK",
- "STICKY_PISTON",
- "STONE",
- "STONE_AXE",
- "STONE_BRICK_SLAB",
- "STONE_BRICK_STAIRS",
- "STONE_BRICK_WALL",
- "STONE_BRICKS",
- "STONE_BUTTON",
- "STONE_HOE",
- "STONE_PICKAXE",
- "STONE_PRESSURE_PLATE",
- "STONE_SHOVEL",
- "STONE_SLAB",
- "STONE_STAIRS",
- "STONE_SWORD",
- "STONECUTTER",
- "STRAY_SPAWN_EGG",
- "STRIDER_SPAWN_EGG",
- "STRING",
- "STRIPPED_ACACIA_LOG",
- "STRIPPED_ACACIA_WOOD",
- "STRIPPED_BAMBOO_BLOCK",
- "STRIPPED_BIRCH_LOG",
- "STRIPPED_BIRCH_WOOD",
- "STRIPPED_CHERRY_LOG",
- "STRIPPED_CHERRY_WOOD",
- "STRIPPED_CRIMSON_HYPHAE",
- "STRIPPED_CRIMSON_STEM",
- "STRIPPED_DARK_OAK_LOG",
- "STRIPPED_DARK_OAK_WOOD",
- "STRIPPED_JUNGLE_LOG",
- "STRIPPED_JUNGLE_WOOD",
- "STRIPPED_MANGROVE_LOG",
- "STRIPPED_MANGROVE_WOOD",
- "STRIPPED_OAK_LOG",
- "STRIPPED_OAK_WOOD",
- "STRIPPED_SPRUCE_LOG",
- "STRIPPED_SPRUCE_WOOD",
- "STRIPPED_WARPED_HYPHAE",
- "STRIPPED_WARPED_STEM",
- "STRUCTURE_BLOCK",
- "STRUCTURE_VOID",
- "SUGAR",
- "SUGAR_CANE",
- "SUNFLOWER",
- "SUSPICIOUS_GRAVEL",
- "SUSPICIOUS_SAND",
- "SUSPICIOUS_STEW",
- "SWEET_BERRIES",
- "SWEET_BERRY_BUSH",
- "TADPOLE_BUCKET",
- "TADPOLE_SPAWN_EGG",
- "TALL_GRASS",
- "TALL_SEAGRASS",
- "TARGET",
- "TERRACOTTA",
- "TIDE_ARMOR_TRIM_SMITHING_TEMPLATE",
- "TINTED_GLASS",
- "TIPPED_ARROW",
- "TNT",
- "TNT_MINECART",
- "TORCH",
- "TORCHFLOWER",
- "TORCHFLOWER_CROP",
- "TORCHFLOWER_SEEDS",
- "TOTEM_OF_UNDYING",
- "TRADER_LLAMA_SPAWN_EGG",
- "TRAPPED_CHEST",
- "TRIAL_KEY",
- "TRIAL_SPAWNER",
- "TRIDENT",
- "TRIPWIRE",
- "TRIPWIRE_HOOK",
- "TROPICAL_FISH",
- "TROPICAL_FISH_BUCKET",
- "TROPICAL_FISH_SPAWN_EGG",
- "TUBE_CORAL",
- "TUBE_CORAL_BLOCK",
- "TUBE_CORAL_FAN",
- "TUBE_CORAL_WALL_FAN",
- "TUFF",
- "TUFF_BRICK_SLAB",
- "TUFF_BRICK_STAIRS",
- "TUFF_BRICK_WALL",
- "TUFF_BRICKS",
- "TUFF_SLAB",
- "TUFF_STAIRS",
- "TUFF_WALL",
- "TURTLE_EGG",
- "TURTLE_HELMET",
- "TURTLE_SPAWN_EGG",
- "TWISTING_VINES",
- "TWISTING_VINES_PLANT",
- "VERDANT_FROGLIGHT",
- "VEX_ARMOR_TRIM_SMITHING_TEMPLATE",
- "VEX_SPAWN_EGG",
- "VILLAGER_SPAWN_EGG",
- "VINDICATOR_SPAWN_EGG",
- "VINE",
- "VOID_AIR",
- "WALL_TORCH",
- "WANDERING_TRADER_SPAWN_EGG",
- "WARD_ARMOR_TRIM_SMITHING_TEMPLATE",
- "WARDEN_SPAWN_EGG",
- "WARPED_BUTTON",
- "WARPED_DOOR",
- "WARPED_FENCE",
- "WARPED_FENCE_GATE",
- "WARPED_FUNGUS",
- "WARPED_FUNGUS_ON_A_STICK",
- "WARPED_HANGING_SIGN",
- "WARPED_HYPHAE",
- "WARPED_NYLIUM",
- "WARPED_PLANKS",
- "WARPED_PRESSURE_PLATE",
- "WARPED_ROOTS",
- "WARPED_SIGN",
- "WARPED_SLAB",
- "WARPED_STAIRS",
- "WARPED_STEM",
- "WARPED_TRAPDOOR",
- "WARPED_WALL_HANGING_SIGN",
- "WARPED_WALL_SIGN",
- "WARPED_WART_BLOCK",
- "WATER",
- "WATER_BUCKET",
- "WATER_CAULDRON",
- "WAXED_CHISELED_COPPER",
- "WAXED_COPPER_BLOCK",
- "WAXED_COPPER_BULB",
- "WAXED_COPPER_DOOR",
- "WAXED_COPPER_GRATE",
- "WAXED_COPPER_TRAPDOOR",
- "WAXED_CUT_COPPER",
- "WAXED_CUT_COPPER_SLAB",
- "WAXED_CUT_COPPER_STAIRS",
- "WAXED_EXPOSED_CHISELED_COPPER",
- "WAXED_EXPOSED_COPPER",
- "WAXED_EXPOSED_COPPER_BULB",
- "WAXED_EXPOSED_COPPER_DOOR",
- "WAXED_EXPOSED_COPPER_GRATE",
- "WAXED_EXPOSED_COPPER_TRAPDOOR",
- "WAXED_EXPOSED_CUT_COPPER",
- "WAXED_EXPOSED_CUT_COPPER_SLAB",
- "WAXED_EXPOSED_CUT_COPPER_STAIRS",
- "WAXED_OXIDIZED_CHISELED_COPPER",
- "WAXED_OXIDIZED_COPPER",
- "WAXED_OXIDIZED_COPPER_BULB",
- "WAXED_OXIDIZED_COPPER_DOOR",
- "WAXED_OXIDIZED_COPPER_GRATE",
- "WAXED_OXIDIZED_COPPER_TRAPDOOR",
- "WAXED_OXIDIZED_CUT_COPPER",
- "WAXED_OXIDIZED_CUT_COPPER_SLAB",
- "WAXED_OXIDIZED_CUT_COPPER_STAIRS",
- "WAXED_WEATHERED_CHISELED_COPPER",
- "WAXED_WEATHERED_COPPER",
- "WAXED_WEATHERED_COPPER_BULB",
- "WAXED_WEATHERED_COPPER_DOOR",
- "WAXED_WEATHERED_COPPER_GRATE",
- "WAXED_WEATHERED_COPPER_TRAPDOOR",
- "WAXED_WEATHERED_CUT_COPPER",
- "WAXED_WEATHERED_CUT_COPPER_SLAB",
- "WAXED_WEATHERED_CUT_COPPER_STAIRS",
- "WAYFINDER_ARMOR_TRIM_SMITHING_TEMPLATE",
- "WEATHERED_CHISELED_COPPER",
- "WEATHERED_COPPER",
- "WEATHERED_COPPER_BULB",
- "WEATHERED_COPPER_DOOR",
- "WEATHERED_COPPER_GRATE",
- "WEATHERED_COPPER_TRAPDOOR",
- "WEATHERED_CUT_COPPER",
- "WEATHERED_CUT_COPPER_SLAB",
- "WEATHERED_CUT_COPPER_STAIRS",
- "WEEPING_VINES",
- "WEEPING_VINES_PLANT",
- "WET_SPONGE",
- "WHEAT",
- "WHEAT_SEEDS",
- "WHITE_BANNER",
- "WHITE_BED",
- "WHITE_CANDLE",
- "WHITE_CANDLE_CAKE",
- "WHITE_CARPET",
- "WHITE_CONCRETE",
- "WHITE_CONCRETE_POWDER",
- "WHITE_DYE",
- "WHITE_GLAZED_TERRACOTTA",
- "WHITE_SHULKER_BOX",
- "WHITE_STAINED_GLASS",
- "WHITE_STAINED_GLASS_PANE",
- "WHITE_TERRACOTTA",
- "WHITE_TULIP",
- "WHITE_WALL_BANNER",
- "WHITE_WOOL",
- "WILD_ARMOR_TRIM_SMITHING_TEMPLATE",
- "WITCH_SPAWN_EGG",
- "WITHER_ROSE",
- "WITHER_SKELETON_SKULL",
- "WITHER_SKELETON_SPAWN_EGG",
- "WITHER_SKELETON_WALL_SKULL",
- "WITHER_SPAWN_EGG",
- "WOLF_SPAWN_EGG",
- "WOODEN_AXE",
- "WOODEN_HOE",
- "WOODEN_PICKAXE",
- "WOODEN_SHOVEL",
- "WOODEN_SWORD",
- "WRITABLE_BOOK",
- "WRITTEN_BOOK",
- "YELLOW_BANNER",
- "YELLOW_BED",
- "YELLOW_CANDLE",
- "YELLOW_CANDLE_CAKE",
- "YELLOW_CARPET",
- "YELLOW_CONCRETE",
- "YELLOW_CONCRETE_POWDER",
- "YELLOW_DYE",
- "YELLOW_GLAZED_TERRACOTTA",
- "YELLOW_SHULKER_BOX",
- "YELLOW_STAINED_GLASS",
- "YELLOW_STAINED_GLASS_PANE",
- "YELLOW_TERRACOTTA",
- "YELLOW_WALL_BANNER",
- "YELLOW_WOOL",
- "ZOGLIN_SPAWN_EGG",
- "ZOMBIE_HEAD",
- "ZOMBIE_HORSE_SPAWN_EGG",
- "ZOMBIE_SPAWN_EGG",
- "ZOMBIE_VILLAGER_SPAWN_EGG",
- "ZOMBIE_WALL_HEAD",
- "ZOMBIFIED_PIGLIN_SPAWN_EGG"
-] \ No newline at end of file
diff --git a/src/data/taskDefinitions.json b/src/data/taskDefinitions.json
deleted file mode 100644
index 443493c..0000000
--- a/src/data/taskDefinitions.json
+++ /dev/null
@@ -1,137 +0,0 @@
-{
- "taskTypes": {
- "blockbreak": {
- "description": "Break a set amount of blocks.",
- "configuration": {
- "amount": {
- "type": "number",
- "description": "The amount of blocks to break.",
- "default": 1,
- "required": true
- },
- "block": {
- "type": "material-list",
- "description": "The specific block to break.",
- "note": "Omitting this value will allow any block to be broken."
- },
- "data": {
- "type": "number",
- "description": "The data value of the block to break.",
- "default": 0,
- "note": "Not required for Minecraft versions 1.13 and above."
- },
- "reverse-if-placed": {
- "type": "boolean",
- "description": "Whether placing blocks should decrement from the quest progress.",
- "default": false
- },
- "allow-negative-progress": {
- "type": "boolean",
- "description": "Whether the quest progress can go into the negatives.",
- "default": false
- },
- "allow-silk-touch": {
- "type": "boolean",
- "description": "Whether blocks broken with a silk touch pickaxe should count towards the quest progress.",
- "default": false
- },
- "check-coreprotect": {
- "type": "boolean",
- "description": "Whether the plugin should query CoreProtect if a block has been recently placed.",
- "default": false,
- "note": "This requires the CoreProtect plugin to be installed."
- },
- "check-coreprotect-time": {
- "type": "number",
- "description": "How long ago (in seconds) the plugin should check with CoreProtect whether a block was placed.",
- "default": false,
- "note": "This requires the CoreProtect plugin to be installed."
- },
- "check-playerblocktracker": {
- "type": "boolean",
- "description": "Whether the plugin should query PlayerBlockTracker if a block has been recently placed.",
- "default": false,
- "note": "This requires the PlayerBlockTracker plugin to be installed."
- },
- "worlds": {
- "type": "string-list",
- "description": "The worlds in which the blocks should be broken."
- }
- }
- },
- "blockplace": {
- "description": "Place a set amount of blocks.",
- "configuration": {
- "amount": {
- "type": "number",
- "description": "The amount of blocks to place.",
- "default": 1,
- "required": true
- },
- "block": {
- "type": "material-list",
- "description": "The specific block to place.",
- "note": "Omitting this value will allow any block to be place."
- },
- "data": {
- "type": "number",
- "description": "The data value of the block to place.",
- "default": 0,
- "note": "Not required for Minecraft versions 1.13 and above."
- },
- "reverse-if-broken": {
- "type": "boolean",
- "description": "Whether breaking blocks should decrement from the quest progress.",
- "default": false
- },
- "worlds": {
- "type": "string-list",
- "description": "The worlds in which the blocks should be broken."
- }
- }
- },
- "inventory": {
- "description": "Obtain a set amount of items.",
- "configuration": {
- "amount": {
- "type": "number",
- "description": "The amount of items to obtain.",
- "default": 1,
- "required": true
- },
- "item": {
- "type": "itemstack",
- "description": "The specific item to obtain.",
- "required": true
- },
- "data": {
- "type": "number",
- "description": "The data value of the item to obtain.",
- "default": 0,
- "note": "Not required for Minecraft versions 1.13 and above."
- },
- "remove-items-when-complete": {
- "type": "boolean",
- "description": "Whether the items should be removed from the player's inventory when the quest is complete.",
- "default": false,
- "note": "If allow-partial-completion is true, this will be set to true as well."
- },
- "allow-partial-completion": {
- "type": "boolean",
- "description": "Whether the quest can be completed with less than the required amount of items.",
- "default": false,
- "note": "Setting to true will imply remove-items-when-complete is true as well. If a player obtains any matching item, it will be immediately taken away from them and added towards the quest progress."
- },
- "exact-match": {
- "type": "boolean",
- "description": "Whether the item must match this item exactly, including lore and enchantments.",
- "default": false
- },
- "worlds": {
- "type": "string-list",
- "description": "The worlds in which the items should be obtained."
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/src/data/testData.json b/src/data/testData.json
deleted file mode 100644
index c01d6c3..0000000
--- a/src/data/testData.json
+++ /dev/null
@@ -1,384 +0,0 @@
-{
- "quests": {
- "example1": {
- "tasks": {
- "mining": {
- "type": "blockbreak",
- "amount": 30
- }
- },
- "display": {
- "name": "&cExample I (Single Task)",
- "lore-normal": [
- "&cThis category is designed to show you the different",
- "&cattributes a quest can have.",
- "",
- "&7This quest requires you to:",
- "&7 - Break &f30 blocks&7.",
- "",
- "&7Rewards:",
- "&7 - &f10 &7diamonds."
- ],
- "lore-started": [
- "",
- "&7Your current progression:",
- "&7 - &f{mining:progress}&7/30 blocks broken."
- ],
- "type": "WOODEN_PICKAXE"
- },
- "rewards": [
- "give {player} diamond 10"
- ],
- "placeholders": {
- "description": "&7Break &f30 blocks &7of any type.",
- "progress": " &8- &f{mining:progress}&7/30 broken"
- },
- "options": {
- "category": "examples",
- "repeatable": false,
- "cooldown": {
- "enabled": true,
- "time": 1440
- },
- "sort-order": 1
- }
- },
- "example2": {
- "tasks": {
- "mining": {
- "type": "blockbreak",
- "amount": 100
- },
- "building": {
- "type": "blockplace",
- "amount": 100
- }
- },
- "display": {
- "name": "&cExample II (Multiple Tasks)",
- "lore-normal": [
- "&cThis category is designed to show you the different",
- "&cattributes a quest can have. This quest requires",
- "&cmultiple things to be done, unlike the previous one.",
- "",
- "&7This quest requires you to:",
- "&7 - Break &f100 &7blocks.",
- "&7 - Place &f100 &7blocks.",
- "",
- "&7Rewards:",
- "&7 - &f15 diamonds&7.",
- "&7 - &f$50&7 added to your in-game balance."
- ],
- "lore-started": [
- "",
- "&7Your current progression:",
- "&7 - &f{mining:progress}&7/100 blocks broken.",
- "&7 - &f{building:progress}&7/100 blocks placed."
- ],
- "type": "GRASS_BLOCK"
- },
- "rewards": [
- "give {player} diamond 15",
- "eco give {player} 50"
- ],
- "placeholders": {
- "description": "&7Break and place &f100 blocks &7of any type.",
- "progress": " &8- &f{mining:progress}&7/100 broken, &f{building:progress}&7/100 placed"
- },
- "options": {
- "category": "examples",
- "requires": [
- "example1"
- ],
- "repeatable": false,
- "cooldown": {
- "enabled": true,
- "time": 1440
- },
- "sort-order": 2
- }
- },
- "example3": {
- "tasks": {
- "mining": {
- "type": "blockbreak",
- "amount": 81,
- "block": "GOLD_ORE"
- },
- "building": {
- "type": "blockplace",
- "amount": 9,
- "block": "GOLD_BLOCK"
- }
- },
- "display": {
- "name": "&cExample III (Repeatable, 10 minute cooldown)",
- "lore-normal": [
- "&cThis category is designed to show you the different",
- "&cattributes a quest can have. This quest can be replayed",
- "&cafter a cooldown, unlike the previous one.",
- "",
- "&7This quest requires you to:",
- "&7 - Break &f81 gold ore&7.",
- "&7 - Place &f9 gold blocks&7.",
- "",
- "&7Rewards:",
- "&7 - &f30 diamonds&7.",
- "&7 - &f$10&7 added to your in-game balance."
- ],
- "lore-started": [
- "",
- "&7Your current progression:",
- "&7 - &f{mining:progress}&7/81 gold ore broken.",
- "&7 - &f{building:progress}&7/9 gold blocks placed."
- ],
- "type": "GOLD_ORE"
- },
- "rewards": [
- "give {player} diamond 30",
- "eco give {player} 10"
- ],
- "placeholders": {
- "description": "&7Break &f81 gold ore &7and place &f9 gold blocks.",
- "progress": " &8- &f{mining:progress}&7/81 gold ore, &f{building:progress}&7/9 gold blocks"
- },
- "options": {
- "category": "examples",
- "requires": [
- "example2"
- ],
- "repeatable": true,
- "cooldown": {
- "enabled": true,
- "time": 10
- },
- "sort-order": 3
- }
- },
- "example4": {
- "tasks": {
- "mobkilling": {
- "type": "mobkilling",
- "amount": 3
- }
- },
- "display": {
- "name": "&cExample IV (Reward String)",
- "lore-normal": [
- "&cThis category is designed to show you the different",
- "&cattributes a quest can have. This quest has a 'reward string'",
- "&c(a series of messages sent when a quest is complete),",
- "&cunlike the previous one.",
- "",
- "&7This quest requires you to:",
- "&7 - Kill &f3 &7mobs.",
- "",
- "&7Rewards:",
- "&7 - &f$50 &7added to your in-game balance.",
- "&7 - &f1 diamond&7."
- ],
- "lore-started": [
- "",
- "&7Your current progression:",
- "&7 - &f{mobkilling:progress}&7/3 mobs killed."
- ],
- "type": "STRING"
- },
- "startstring": [
- "&7Upon completion of this quest, you will be rewarded with",
- " &8* &c$50",
- " &8* &c1 diamonds"
- ],
- "rewards": [
- "eco give {player} 50",
- "give {player} diamond 1"
- ],
- "placeholders": {
- "description": "&7Kill &f3 &7mobs.",
- "progress": " &8- &f{mobkilling:progress}&7/3 mobs"
- },
- "rewardstring": [
- " &8* &c$1000 &7was added to your in-game balance.",
- " &8* &c1 diamond &7was added to your inventory."
- ],
- "options": {
- "category": "examples",
- "requires": [
- "example3"
- ],
- "repeatable": true,
- "cooldown": {
- "enabled": true,
- "time": 10
- },
- "sort-order": 4
- }
- },
- "example5": {
- "tasks": {
- "building": {
- "type": "blockplace",
- "amount": 10
- }
- },
- "display": {
- "name": "&cExample V (Permission)",
- "lore-normal": [
- "&cThis category is designed to show you the different",
- "&cattributes a quest can have. This quest requires",
- "&ccertain permissions.",
- "",
- "&7This quest requires you to:",
- "&7 - Place &f10 &7blocks.",
- "",
- "&7Rewards:",
- "&7 - &f$10 &7added to your in-game balance."
- ],
- "lore-started": [
- "",
- "&7Your current progression:",
- "&7 - &f{building:progress}&7/10 blocks placed."
- ],
- "type": "GRASS_BLOCK"
- },
- "rewards": [
- "eco give {player} 10"
- ],
- "placeholders": {
- "description": "&7Place &f10 &7blocks of any type.",
- "progress": " &8- &f{building:progress}&7/10 blocks"
- },
- "options": {
- "category": "examples",
- "requires": [
- "example4"
- ],
- "permission-required": true,
- "repeatable": false,
- "cooldown": {
- "enabled": true,
- "time": 1440
- },
- "sort-order": 5
- }
- },
- "example6": {
- "tasks": {
- "building": {
- "type": "blockplace",
- "amount": 10
- }
- },
- "display": {
- "name": "&cExample VI (Different category, permissions)",
- "lore-normal": [
- "&cThis category is designed to show you the different",
- "&cattributes a quest can have. This quest requires",
- "&ccertain permissions.",
- "",
- "&7This quest requires you to:",
- "&7 - Place &f10 &7blocks.",
- "",
- "&7Rewards:",
- "&7 - &f$10 &7added to your in-game balance."
- ],
- "lore-started": [
- "",
- "&7Your current progression:",
- "&7 - &f{building:progress}&7/10 blocks placed."
- ],
- "type": "GRASS_BLOCK"
- },
- "rewards": [
- "eco give {player} 10"
- ],
- "placeholders": {
- "description": "&7Place &f10 &7blocks of any type.",
- "progress": " &8- &f{building:progress}&7/10 blocks"
- },
- "options": {
- "category": "permissionexample",
- "repeatable": false,
- "cooldown": {
- "enabled": true,
- "time": 1440
- },
- "sort-order": 1
- }
- },
- "example7": {
- "tasks": {
- "building": {
- "type": "blockplace",
- "amount": 10,
- "worlds": [
- "world"
- ]
- }
- },
- "display": {
- "name": "&cExample VII (Different category, world restricted)",
- "lore-normal": [
- "&cThis category is designed to show you the different",
- "&cattributes a quest can have. This quest requires",
- "&chas a task which requires you to be in a world called 'world'.",
- "",
- "&7This quest requires you to:",
- "&7 - Place &f10 &7blocks.",
- "",
- "&7Rewards:",
- "&7 - &f$10 &7added to your in-game balance."
- ],
- "lore-started": [
- "",
- "&7Your current progression:",
- "&7 - &f{building:progress}&7/10 blocks placed."
- ],
- "type": "GRASS_BLOCK"
- },
- "rewards": [
- "eco give {player} 10"
- ],
- "placeholders": {
- "description": "&7Place &f10 &7blocks of any type in world &fworld.",
- "progress": " &8- &f{building:progress}&7/10 blocks"
- },
- "options": {
- "category": "permissionexample",
- "repeatable": false,
- "cooldown": {
- "enabled": true,
- "time": 1440
- },
- "sort-order": 1
- }
- }
- },
- "categories": {
- "examples": {
- "display": {
- "name": "&cExamples",
- "lore": [
- "&cThis category is designed to show you the different",
- "&cattributes a quest can have."
- ],
- "type": "WOODEN_SWORD"
- }
- },
- "permissionexample": {
- "display": {
- "name": "&cPermission Example",
- "lore": [
- "&7This category is an example of one which",
- "&7requires a permission to open.",
- "",
- "&cIt is highly recommended you read this",
- "&csection and all the comments so you can",
- "&cmake the most of this plugin."
- ],
- "type": "WATER_BUCKET"
- },
- "permission-required": true
- }
- }
-} \ No newline at end of file
diff --git a/src/lib/materials.ts b/src/lib/materials.ts
deleted file mode 100644
index 36c5aee..0000000
--- a/src/lib/materials.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import materials from '@/data/materials.json';
-
-export default materials; \ No newline at end of file
diff --git a/src/lib/questsLoader.ts b/src/lib/questsLoader.ts
deleted file mode 100644
index 0623f04..0000000
--- a/src/lib/questsLoader.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import type { EditorQuest, EditorTask, EditorCategory } from '../stores/session';
-
-export function loadQuestsFromJson(config: any): EditorQuest[] {
- return Object.keys(config).map((questid: any) => {
- const quest = config[questid];
-
- return {
- id: questid,
- display: {
- name: quest.display.name,
- lore: {
- normal: quest.display['lore-normal'],
- started: quest.display['lore-started'],
- },
- type: quest.display.type,
- },
- tasks: Object.fromEntries(Object.keys(quest.tasks).map((taskId: string) => {
- return [taskId, {
- id: taskId,
- config: quest.tasks[taskId],
- } as EditorTask];
- })),
- rewards: quest.rewards,
- ...(quest.startcommands && { startCommands: quest.startcommands }),
- ...(quest.startstring && { startString: quest.startstring }),
- ...(quest.rewardstring && { rewardString: quest.rewardstring }),
- ...(quest.placeholders && { placeholders: quest.placeholders }),
- options: {
- category: quest.options.category,
- requirements: quest.options.requires || [],
- permissionRequired: quest.options['permission-required'] || false,
- cancellable: quest.options.cancellable || false,
- countsTowardsLimit: quest.options['counts-towards-limit'] || true,
- repeatable: quest.options.repeatable || false,
- cooldown: {
- enabled: quest.options.cooldown?.enabled || false,
- time: quest.options.cooldown?.time || 0,
- },
- timeLimit: {
- enabled: quest.options['time-limit']?.enabled || false,
- time: quest.options['time-limit']?.time || 0,
- },
- sortOrder: quest.options['sort-order'] || 0,
- autostart: quest.options.autostart || false,
- ...(quest.options['completed-display'] && { completedDisplay: quest.options['completed-display'] }),
- ...(quest.options['cooldown-display'] && { cooldownDisplay: quest.options['cooldown-display'] }),
- ...(quest.options['permission-display'] && { permissionDisplay: quest.options['permission-display'] }),
- ...(quest.options['locked-display'] && { lockedDisplay: quest.options['locked-display'] }),
- },
- } as EditorQuest;
- });
-}
-
-export function loadCategoriesFromJson(config: any): EditorCategory[] {
- return Object.keys(config).map((categoryid: any) => {
- const category = config[categoryid];
-
- return {
- id: categoryid,
- display: {
- name: category.display.name,
- lore: category.display.lore,
- type: category.display.type,
- },
- permissionRequired: category['permission-required'],
- };
- });
-}
diff --git a/src/lib/util.ts b/src/lib/util.ts
deleted file mode 100644
index b8be8cb..0000000
--- a/src/lib/util.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-const COLOR_CODE_REGEX = /&[0-9a-fk-or]/i;
-const VALID_ID_REGEX = /^[a-z0-9_]+$/i;
-
-export function stripColorCodes(str: string): string {
- return str.replace(COLOR_CODE_REGEX, '');
-}
-
-export function validateQuestId(id: string): boolean {
- return VALID_ID_REGEX.test(id);
-}
-
-export function validateCategoryId(id: string): boolean {
- return VALID_ID_REGEX.test(id);
-}
-
-export function validateTaskId(id: string): boolean {
- return VALID_ID_REGEX.test(id);
-} \ No newline at end of file
diff --git a/src/main.ts b/src/main.ts
deleted file mode 100644
index 74e9999..0000000
--- a/src/main.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import './assets/main.css'
-
-import { createApp } from 'vue'
-import { createPinia } from 'pinia'
-import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
-import { library } from "@fortawesome/fontawesome-svg-core";
-import { faFolder, faCaretDown, faCaretUp, faChevronRight, faTriangleExclamation, faPen, faTrash, faCode, faCheck, faXmark, faPlus, faCopy, faSave, faCube, faTag, faAppleWhole } from "@fortawesome/free-solid-svg-icons";
-import { faCompass } from '@fortawesome/free-regular-svg-icons';
-
-import App from './App.vue'
-import Multiselect from 'vue-multiselect'
-import router from './router'
-
-const app = createApp(App)
-
-library.add(faFolder);
-library.add(faCaretDown);
-library.add(faCaretUp);
-library.add(faChevronRight);
-library.add(faCompass);
-library.add(faTriangleExclamation);
-library.add(faPen);
-library.add(faTrash);
-library.add(faCode);
-library.add(faCheck);
-library.add(faXmark);
-library.add(faPlus);
-library.add(faCopy);
-library.add(faSave);
-library.add(faCube);
-library.add(faTag);
-library.add(faAppleWhole);
-
-app.component('font-awesome-icon', FontAwesomeIcon)
-app.component('multiselect', Multiselect)
-
-app.use(createPinia())
-app.use(router)
-
-app.mount('#app')
diff --git a/src/router/index.ts b/src/router/index.ts
deleted file mode 100644
index 9091d16..0000000
--- a/src/router/index.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { createRouter, createWebHistory } from 'vue-router'
-import EditorView from '../views/EditorView.vue'
-
-const router = createRouter({
- history: createWebHistory(import.meta.env.BASE_URL),
- routes: [
- {
- path: '/',
- name: 'home',
- component: EditorView
- },
- {
- path: '/about',
- name: 'about',
- // route level code-splitting
- // this generates a separate chunk (About.[hash].js) for this route
- // which is lazy-loaded when the route is visited.
- component: () => import('../views/EditorView.vue')
- }
- ]
-})
-
-export default router
diff --git a/src/stores/session.ts b/src/stores/session.ts
deleted file mode 100644
index 1cc8dc7..0000000
--- a/src/stores/session.ts
+++ /dev/null
@@ -1,171 +0,0 @@
-import { defineStore } from 'pinia'
-
-export interface EditorQuest {
- id: string;
- display: {
- name: string;
- lore: {
- normal: string[];
- started: string[];
- }
- type: string;
- }
- tasks: { [key: string]: EditorTask };
- rewards: string[];
- startCommands?: string[];
- startString?: string[];
- rewardString?: string[];
- placeholders?: { [key: string]: string };
- options: {
- category: string;
- requirements: string[];
- permissionRequired: boolean;
- cancellable: boolean;
- countsTowardsLimit: boolean;
- repeatable: boolean;
- cooldown: {
- enabled: boolean;
- time: number;
- }
- timeLimit: {
- enabled: boolean;
- time: number;
- }
- sortOrder: number;
- autostart: boolean;
- completedDisplay?: string;
- cooldownDisplay?: string;
- permissionDisplay?: string;
- lockedDisplay?: string;
- }
-}
-
-export interface EditorTask {
- id: string;
- config: {
- type: string;
- [key: string]: any;
- }
-}
-
-export interface EditorCategory {
- id: string;
- display: {
- name: string;
- lore: string[];
- type: string;
- }
- permissionRequired: string;
-}
-
-export interface TaskDefinition {
- description: string;
- configuration: {
- [key: string]: {
- type: string | string[];
- description: string;
- default?: any;
- required?: boolean;
- note?: string;
- }
- }
-}
-
-export const useSessionStore = defineStore('session', {
- state: () => ({
- sessionType: '',
- session: {
- quests: [] as EditorQuest[],
- categories: [] as EditorCategory[],
- taskDefinitions: {} as { [key: string]: TaskDefinition },
- },
- editor: {
- selected: {
- type: '' as 'Quest' | 'Category' | null,
- id: '' as string | null,
- }
- }
- }),
- getters: {
- getSessionType(): string {
- return this.sessionType
- },
- getQuests(): EditorQuest[] {
- return this.session.quests
- },
- getCategories(): EditorCategory[] {
- return this.session.categories
- },
- getQuestById: (state) => (id: string) => {
- if (!id) return null;
- return state.session.quests.find(quest => quest.id === id)
- },
- getCategoryById: (state) => (id: string) => {
- if (!id) return null;
- return state.session.categories.find(quest => quest.id === id)
- },
- getQuestsInCategory: (state) => (id: string) => {
- if (!id) return [];
- return state.session.quests.filter(quest => quest.options.category === id)
- },
- getTaskDefinitions: (state) => {
- return state.session.taskDefinitions
- },
- getTaskDefinitionByTaskType: (state) => (type: string) => {
- return state.session.taskDefinitions[type]
- },
- getKnownTaskTypes: (state) => () => {
- return Object.keys(state.session.taskDefinitions)
- }
- // getEditorCategories: (state) => {
- // return state.editor.categories
- // }
- },
- actions: {
- setSessionType(type: string) {
- this.sessionType = type
- },
- setQuests(quests: EditorQuest[]) {
- this.session.quests = quests
- },
- setCategories(categories: EditorCategory[]) {
- this.session.categories = categories
- },
- // updateEditorCategories() {
- // const categories: { [key: string]: { quests: string[] } } = {}
- // this.session.categories.forEach(category => {
- // categories[category.id] = { quests: [] }
- // })
- // this.session.quests.forEach(quest => {
- // categories[quest.options.category].quests.push(quest.id)
- // })
- // this.editor.categories = categories;
- // },
- setEditorSelected(type: 'Quest' | 'Category' | null, id: string | null) {
- this.editor.selected.type = type
- this.editor.selected.id = id
- },
- setTaskDefinitions(definitions: { [key: string]: TaskDefinition }) {
- this.session.taskDefinitions = definitions
- },
- changeQuestId(oldId: string, newId: string) {
- const quest = this.getQuestById(oldId);
- if (!quest) return;
-
- quest.id = newId
- },
- deleteQuest(id: string) {
- const index = this.session.quests.findIndex(quest => quest.id === id)
- if (index === -1) return;
- this.session.quests.splice(index, 1)
- },
- duplicateQuest(id: string, newQuestId: string) {
- const quest = this.getQuestById(id);
- if (!quest) return;
-
- const newQuest = JSON.parse(JSON.stringify(quest));
- newQuest.id = newQuestId;
- this.session.quests.push(newQuest);
- }
- }
-});
diff --git a/src/views/EditorView.vue b/src/views/EditorView.vue
deleted file mode 100644
index b94f998..0000000
--- a/src/views/EditorView.vue
+++ /dev/null
@@ -1,37 +0,0 @@
-<script setup lang="ts">
-import { useSessionStore } from '@/stores/session';
-import { loadQuestsFromJson, loadCategoriesFromJson } from '@/lib/questsLoader';
-import EditorSidebar from '@/components/Editor/EditorSidebar.vue';
-import testData from '@/data/testData.json';
-import taskDefinitions from '@/data/taskDefinitions.json';
-import EditorPane from '@/components/Editor/EditorPane.vue';
-
-const sessionStore = useSessionStore();
-
-const quests = loadQuestsFromJson(testData.quests);
-const categories = loadCategoriesFromJson(testData.categories);
-
-sessionStore.setQuests(quests);
-sessionStore.setCategories(categories);
-sessionStore.setTaskDefinitions(taskDefinitions.taskTypes);
-// sessionStore.updateEditorCategories();
-</script>
-
-<template>
- <main>
- <div id="editor-container">
- <EditorSidebar />
-
- <EditorPane />
- </div>
- </main>
-</template>
-
-<style lang="scss" scoped>
-#editor-container {
- display: flex;
- background-color: var(--color-background-soft);
- max-height: calc(100vh - 73px);
- flex-direction: row;
-}
-</style> \ No newline at end of file