diff options
Diffstat (limited to 'src')
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 Binary files differdeleted file mode 100644 index 0d0194f..0000000 --- a/src/assets/quests-logo.png +++ /dev/null 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 |
