You've already forked AstralRinth
forked from didirus/AstralRinth
Datapack support (#815)
* Shader support PR * Make search page work * Fix env showing * Make moderation look reasonable * Fix search for shaders * Datapack support * Make file types work + datapack inferring * Add editing to file types * Finish datapack file generation * Fix bugs, make forge support work * Fix inconsistent data pack label * Final fixes
This commit is contained in:
@@ -85,7 +85,14 @@
|
||||
border-bottom: 1px solid var(--color-header-underline);
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, li, p {
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
li,
|
||||
p {
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
@@ -227,11 +234,17 @@
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
iframe,
|
||||
video {
|
||||
aspect-ratio: 16 / 9;
|
||||
width: 850px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 850px) {
|
||||
iframe {
|
||||
aspect-ratio: 16 / 9;
|
||||
iframe,
|
||||
video {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -332,8 +345,8 @@
|
||||
}
|
||||
|
||||
.button-animation {
|
||||
transition: opacity 0.5s ease-in-out, filter 0.2s ease-in-out, transform 0.05s ease-in-out,
|
||||
outline 0.2s ease-in-out;
|
||||
transition: opacity 0.5s ease-in-out, filter 0.2s ease-in-out,
|
||||
transform 0.05s ease-in-out, outline 0.2s ease-in-out;
|
||||
|
||||
&:active:not(&:disabled) {
|
||||
transform: scale(0.95);
|
||||
@@ -403,8 +416,8 @@ tr.button-transparent {
|
||||
}
|
||||
|
||||
.button-within {
|
||||
transition: opacity 0.5s ease-in-out, filter 0.2s ease-in-out, transform 0.05s ease-in-out,
|
||||
outline 0.2s ease-in-out;
|
||||
transition: opacity 0.5s ease-in-out, filter 0.2s ease-in-out,
|
||||
transform 0.05s ease-in-out, outline 0.2s ease-in-out;
|
||||
|
||||
&:focus-visible:not(&.disabled),
|
||||
&:hover:not(&.disabled) {
|
||||
@@ -541,6 +554,11 @@ tr.button-transparent {
|
||||
--text-color: var(--color-brand-inverted);
|
||||
}
|
||||
|
||||
.alt-brand-button {
|
||||
--background-color: var(--color-brand-highlight);
|
||||
--text-color: var(--color-text);
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
grid-gap: var(--spacing-card-sm);
|
||||
@@ -563,6 +581,15 @@ tr.button-transparent {
|
||||
}
|
||||
|
||||
.multiselect {
|
||||
&.raised-multiselect {
|
||||
.multiselect__tags,
|
||||
.multiselect__content-wrapper,
|
||||
.multiselect__spinner {
|
||||
background-color: var(--color-raised-bg);
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
color: var(--color-text) !important;
|
||||
outline: 2px solid transparent;
|
||||
|
||||
@@ -584,7 +611,7 @@ tr.button-transparent {
|
||||
padding-left: 7px;
|
||||
padding-top: 10px;
|
||||
|
||||
transition: background-color .1s ease-in-out;
|
||||
transition: background-color 0.1s ease-in-out;
|
||||
|
||||
&:active {
|
||||
background: var(--color-button-bg-hover);
|
||||
@@ -790,7 +817,7 @@ tr.button-transparent {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
grid-gap: .5rem;
|
||||
grid-gap: 0.5rem;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
@@ -929,7 +956,10 @@ h1 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.nuxt-link-exact-active, h1, h2, h3 {
|
||||
.nuxt-link-exact-active,
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
.beta-badge {
|
||||
background-color: var(--color-button-text-active);
|
||||
box-sizing: border-box;
|
||||
@@ -939,7 +969,8 @@ h1 {
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion) {
|
||||
.button-animation, button {
|
||||
.button-animation,
|
||||
button {
|
||||
transform: none !important;
|
||||
}
|
||||
}
|
||||
@@ -965,7 +996,7 @@ h1 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
grid-gap: .5rem;
|
||||
grid-gap: 0.5rem;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
@@ -986,7 +1017,8 @@ h1 {
|
||||
}
|
||||
|
||||
.universal-labels {
|
||||
label, .label {
|
||||
label,
|
||||
.label {
|
||||
.label__title {
|
||||
display: block;
|
||||
margin-block: var(--spacing-card-md) var(--spacing-card-sm);
|
||||
@@ -1074,13 +1106,16 @@ h1 {
|
||||
}
|
||||
|
||||
.input-group {
|
||||
.multiselect, input {
|
||||
.multiselect,
|
||||
input {
|
||||
width: auto;
|
||||
flex-basis: 0;
|
||||
}
|
||||
}
|
||||
|
||||
button, .button, .iconified-button {
|
||||
button,
|
||||
.button,
|
||||
.iconified-button {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
@@ -1095,12 +1130,14 @@ h1 {
|
||||
}
|
||||
}
|
||||
|
||||
.adjacent-input, &.adjacent-input {
|
||||
.adjacent-input,
|
||||
&.adjacent-input {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.iconified-button, .input-group {
|
||||
.iconified-button,
|
||||
.input-group {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@@ -1152,7 +1189,9 @@ h1 {
|
||||
}
|
||||
|
||||
.full-width-inputs {
|
||||
.multiselect, input, .iconified-input {
|
||||
.multiselect,
|
||||
input,
|
||||
.iconified-input {
|
||||
width: 100%;
|
||||
flex-basis: 100%;
|
||||
}
|
||||
@@ -1286,7 +1325,8 @@ button {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
input, textarea {
|
||||
input,
|
||||
textarea {
|
||||
border-radius: 0;
|
||||
background-color: transparent;
|
||||
box-shadow: unset;
|
||||
@@ -1294,8 +1334,10 @@ button {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&:focus, &:focus-visible, &:focus-within {
|
||||
box-shadow: inset 0 0 0 transparent, 0 0 0 .25rem var(--color-brand-shadow);
|
||||
&:focus,
|
||||
&:focus-visible,
|
||||
&:focus-within {
|
||||
box-shadow: inset 0 0 0 transparent, 0 0 0 0.25rem var(--color-brand-shadow);
|
||||
color: var(--color-button-text-active);
|
||||
}
|
||||
}
|
||||
@@ -1365,7 +1407,8 @@ button {
|
||||
}
|
||||
|
||||
@media screen and (max-width: 550px) {
|
||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,8 +61,8 @@ html {
|
||||
--color-special-orange: #e08325;
|
||||
--color-special-green: var(--color-brand-green);
|
||||
--color-special-blue: #1f68c0;
|
||||
--color-special-purple: #8e32F3;
|
||||
--color-special-gray: #595B61;
|
||||
--color-special-purple: #8e32f3;
|
||||
--color-special-gray: #595b61;
|
||||
|
||||
--color-warning-bg: hsl(355, 70%, 88%);
|
||||
--color-warning-text: hsl(342, 70%, 35%);
|
||||
@@ -86,8 +86,9 @@ html {
|
||||
--shadow-raised: 0.3px 0.5px 0.6px hsl(var(--shadow-color) / 0.15),
|
||||
1px 2px 2.2px -1.7px hsl(var(--shadow-color) / 0.12),
|
||||
4.4px 8.8px 9.7px -3.4px hsl(var(--shadow-color) / 0.09);
|
||||
--shadow-floating: hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0) 0px 0px 0px 0px,
|
||||
hsla(0, 0%, 0%, 0.1) 0px 4px 6px -1px, hsla(0, 0%, 0%, 0.1) 0px 2px 4px -1px;
|
||||
--shadow-floating: hsla(0, 0%, 0%, 0) 0px 0px 0px 0px,
|
||||
hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0.1) 0px 4px 6px -1px,
|
||||
hsla(0, 0%, 0%, 0.1) 0px 2px 4px -1px;
|
||||
|
||||
--shadow-card: rgba(50, 50, 100, 0.1) 0px 2px 4px 0px;
|
||||
}
|
||||
@@ -109,9 +110,9 @@ html {
|
||||
--color-special-red: #ff496e;
|
||||
--color-special-orange: #ffa347;
|
||||
--color-special-green: var(--color-brand-green);
|
||||
--color-special-blue: #4F9CFF;
|
||||
--color-special-purple: #C78AFF;
|
||||
--color-special-gray: #9FA4B3;
|
||||
--color-special-blue: #4f9cff;
|
||||
--color-special-purple: #c78aff;
|
||||
--color-special-gray: #9fa4b3;
|
||||
|
||||
--color-brand-green: #1bd96a;
|
||||
--color-brand: var(--color-brand-green);
|
||||
@@ -168,8 +169,9 @@ html {
|
||||
|
||||
--shadow-raised-lg: 0px 2px 4px hsla(221, 39%, 11%, 0.2);
|
||||
--shadow-raised: 0px -2px 4px hsla(221, 39%, 11%, 0.1);
|
||||
--shadow-floating: hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0) 0px 0px 0px 0px,
|
||||
hsla(0, 0%, 0%, 0.1) 0px 4px 6px -1px, rgba(0, 0, 0, 0.06) 0px 2px 4px -1px;
|
||||
--shadow-floating: hsla(0, 0%, 0%, 0) 0px 0px 0px 0px,
|
||||
hsla(0, 0%, 0%, 0) 0px 0px 0px 0px, hsla(0, 0%, 0%, 0.1) 0px 4px 6px -1px,
|
||||
rgba(0, 0, 0, 0.06) 0px 2px 4px -1px;
|
||||
|
||||
--shadow-card: rgba(0, 0, 0, 0.25) 0px 2px 4px 0px;
|
||||
}
|
||||
@@ -194,8 +196,10 @@ body {
|
||||
// Defaults
|
||||
background-color: var(--color-bg);
|
||||
color: var(--color-text);
|
||||
--font-standard: Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Roboto, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
--mono-font: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
|
||||
--font-standard: Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen,
|
||||
Ubuntu, Roboto, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
--mono-font: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas,
|
||||
Liberation Mono, monospace;
|
||||
font-family: var(--font-standard);
|
||||
font-size: 16px;
|
||||
font-weight: var(--font-weight-regular);
|
||||
@@ -216,7 +220,7 @@ body {
|
||||
|
||||
--size-navbar-height: 3.5rem;
|
||||
--size-mobile-navbar-height: 3.5rem;
|
||||
--size-mobile-navbar-height-expanded: 11.75rem;
|
||||
--size-mobile-navbar-height-expanded: 13.75rem;
|
||||
|
||||
--spacing-card-lg: 1.5rem;
|
||||
--spacing-card-bg: 1rem;
|
||||
@@ -245,11 +249,15 @@ body {
|
||||
--font-weight-heading: var(--font-weight-extrabold);
|
||||
--font-weight-title: var(--font-weight-extrabold);
|
||||
|
||||
@media screen and (min-width: 318px) {
|
||||
@media screen and (min-width: 320px) {
|
||||
--size-mobile-navbar-height-expanded: 11.5rem;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 432px) {
|
||||
--size-mobile-navbar-height-expanded: 9.25rem;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 625px) {
|
||||
@media screen and (min-width: 765px) {
|
||||
--size-mobile-navbar-height-expanded: 7rem;
|
||||
}
|
||||
}
|
||||
@@ -304,8 +312,9 @@ textarea {
|
||||
transition: box-shadow 0.1s ease-in-out;
|
||||
min-height: 40px;
|
||||
|
||||
&:focus, &:focus-visible {
|
||||
box-shadow: inset 0 0 0 transparent, 0 0 0 .25rem var(--color-brand-shadow);
|
||||
&:focus,
|
||||
&:focus-visible {
|
||||
box-shadow: inset 0 0 0 transparent, 0 0 0 0.25rem var(--color-brand-shadow);
|
||||
color: var(--color-button-text-active);
|
||||
}
|
||||
|
||||
@@ -326,7 +335,8 @@ textarea {
|
||||
}
|
||||
}
|
||||
|
||||
button, input[type=button] {
|
||||
button,
|
||||
input[type='button'] {
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
outline: 2px solid transparent;
|
||||
@@ -348,7 +358,9 @@ kbd {
|
||||
@import '~assets/styles/components.scss';
|
||||
@import '~assets/styles/normalize.scss';
|
||||
|
||||
button:focus-visible, a:focus-visible, [tabindex="0"]:focus-visible {
|
||||
outline: .25rem solid #ea80ff;
|
||||
border-radius: .25rem;
|
||||
button:focus-visible,
|
||||
a:focus-visible,
|
||||
[tabindex='0']:focus-visible {
|
||||
outline: 0.25rem solid #ea80ff;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
@@ -27,9 +27,12 @@ export default {
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
document.addEventListener('dragenter', () => {
|
||||
this.$refs.drop_area.style.visibility = 'visible'
|
||||
})
|
||||
// eslint-disable-next-line nuxt/no-env-in-hooks
|
||||
if (process.client) {
|
||||
document.addEventListener('dragenter', () => {
|
||||
this.$refs.drop_area.style.visibility = 'visible'
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
allowDrag(event) {
|
||||
|
||||
@@ -123,6 +123,8 @@ export default {
|
||||
return 'required'
|
||||
case 'shader':
|
||||
return 'required'
|
||||
case 'datapack':
|
||||
return 'optional'
|
||||
default:
|
||||
return 'unknown'
|
||||
}
|
||||
@@ -135,6 +137,8 @@ export default {
|
||||
return 'unsupported'
|
||||
case 'shader':
|
||||
return 'unsupported'
|
||||
case 'datapack':
|
||||
return 'required'
|
||||
default:
|
||||
return 'unknown'
|
||||
}
|
||||
|
||||
@@ -50,7 +50,15 @@
|
||||
<p class="description">
|
||||
{{ description }}
|
||||
</p>
|
||||
<Categories :categories="categories" :type="type" class="tags">
|
||||
<Categories
|
||||
:categories="
|
||||
categories.filter(
|
||||
(x) => !hideLoaders || !$tag.loaders.find((y) => y.name === x)
|
||||
)
|
||||
"
|
||||
:type="type"
|
||||
class="tags"
|
||||
>
|
||||
<span v-if="moderation" class="environment">
|
||||
<InfoIcon aria-hidden="true" />
|
||||
A {{ projectTypeDisplay }}
|
||||
@@ -58,7 +66,8 @@
|
||||
<span
|
||||
v-else-if="
|
||||
!['resourcepack', 'shader'].includes(type) &&
|
||||
!(projectTypeDisplay === 'plugin' && search)
|
||||
!(projectTypeDisplay === 'plugin' && search) &&
|
||||
!categories.some((x) => $tag.loaderData.dataPackLoaders.includes(x))
|
||||
"
|
||||
class="environment"
|
||||
>
|
||||
@@ -261,6 +270,11 @@ export default {
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
hideLoaders: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
projectTypeDisplay() {
|
||||
|
||||
@@ -31,8 +31,7 @@ export default {
|
||||
.filter(
|
||||
(x) =>
|
||||
this.categories.includes(x.name) &&
|
||||
(!x.project_type || x.project_type === this.type) &&
|
||||
x.name !== 'minecraft'
|
||||
(!x.project_type || x.project_type === this.type)
|
||||
)
|
||||
},
|
||||
},
|
||||
|
||||
@@ -32,12 +32,16 @@
|
||||
label: 'Plugins',
|
||||
href: '/plugins',
|
||||
},
|
||||
{
|
||||
label: 'Data Packs',
|
||||
href: '/datapacks',
|
||||
},
|
||||
{
|
||||
label: 'Shaders',
|
||||
href: '/shaders',
|
||||
},
|
||||
{
|
||||
label: 'Resourcepacks',
|
||||
label: 'Resource Packs',
|
||||
href: '/resourcepacks',
|
||||
},
|
||||
{
|
||||
@@ -201,6 +205,14 @@
|
||||
>
|
||||
<span>Plugins</span>
|
||||
</NuxtLink>
|
||||
<NuxtLink
|
||||
:tabindex="isBrowseMenuOpen ? 0 : -1"
|
||||
to="/datapacks"
|
||||
class="tab iconified-button"
|
||||
@click.native="isBrowseMenuOpen = false"
|
||||
>
|
||||
<span>Data packs</span>
|
||||
</NuxtLink>
|
||||
<NuxtLink
|
||||
:tabindex="isBrowseMenuOpen ? 0 : -1"
|
||||
to="/shaders"
|
||||
@@ -215,7 +227,7 @@
|
||||
class="tab iconified-button"
|
||||
@click.native="isBrowseMenuOpen = false"
|
||||
>
|
||||
<span>Resourcepacks</span>
|
||||
<span>Resource packs</span>
|
||||
</NuxtLink>
|
||||
<NuxtLink
|
||||
:tabindex="isBrowseMenuOpen ? 0 : -1"
|
||||
@@ -487,12 +499,13 @@ export default {
|
||||
watch: {
|
||||
$route() {
|
||||
this.isMobileMenuOpen = false
|
||||
document.body.style.overflowY = 'scroll'
|
||||
|
||||
this.$store.dispatch('user/fetchAll')
|
||||
|
||||
document.body.setAttribute('tabindex', '-1')
|
||||
document.body.removeAttribute('tabindex')
|
||||
if (process.client) {
|
||||
document.body.style.overflowY = 'scroll'
|
||||
document.body.setAttribute('tabindex', '-1')
|
||||
document.body.removeAttribute('tabindex')
|
||||
}
|
||||
},
|
||||
},
|
||||
beforeCreate() {
|
||||
@@ -848,7 +861,7 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 750px) {
|
||||
@media screen and (max-width: 1024px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -963,7 +976,7 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 750px) {
|
||||
@media screen and (max-width: 1024px) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ export default {
|
||||
hid: 'description',
|
||||
name: 'description',
|
||||
content:
|
||||
'Download Minecraft mods, plugins, resource packs, and modpacks on Modrinth. Discover and publish projects on Modrinth with a modern, easy to use interface and API.',
|
||||
'Download Minecraft mods, plugins, datapacks, shaders, resourcepacks, and modpacks on Modrinth. Discover and publish projects on Modrinth with a modern, easy to use interface and API.',
|
||||
},
|
||||
{
|
||||
hid: 'publisher',
|
||||
@@ -170,6 +170,11 @@ export default {
|
||||
component: resolve(__dirname, 'pages/search/shaders.vue'),
|
||||
name: 'shaders',
|
||||
},
|
||||
{
|
||||
path: '/datapacks',
|
||||
component: resolve(__dirname, 'pages/search/datapacks.vue'),
|
||||
name: 'datapacks',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
|
||||
@@ -45,7 +45,9 @@
|
||||
<div
|
||||
v-if="
|
||||
project.project_type !== 'resourcepack' &&
|
||||
project.project_type !== 'plugin'
|
||||
project.project_type !== 'plugin' &&
|
||||
project.project_type !== 'shader' &&
|
||||
project.project_type !== 'datapack'
|
||||
"
|
||||
>
|
||||
<div
|
||||
@@ -502,7 +504,8 @@
|
||||
v-if="
|
||||
project.project_type !== 'resourcepack' &&
|
||||
project.project_type !== 'plugin' &&
|
||||
project.project_type !== 'shader'
|
||||
project.project_type !== 'shader' &&
|
||||
project.project_type !== 'datapack'
|
||||
"
|
||||
class="info"
|
||||
>
|
||||
@@ -515,7 +518,8 @@
|
||||
v-if="
|
||||
project.project_type !== 'resourcepack' &&
|
||||
project.project_type !== 'plugin' &&
|
||||
project.project_type !== 'shader'
|
||||
project.project_type !== 'shader' &&
|
||||
project.project_type !== 'datapack'
|
||||
"
|
||||
class="info"
|
||||
>
|
||||
@@ -843,10 +847,9 @@ export default {
|
||||
this.featuredVersions = this.$computeVersions(this.featuredVersions)
|
||||
},
|
||||
head() {
|
||||
const title = `${this.project.title} - Minecraft ${
|
||||
this.projectTypeDisplay.charAt(0).toUpperCase() +
|
||||
this.projectTypeDisplay.slice(1)
|
||||
}`
|
||||
const title = `${this.project.title} - Minecraft ${this.$formatProjectType(
|
||||
this.projectTypeDisplay
|
||||
)}`
|
||||
|
||||
return {
|
||||
title,
|
||||
@@ -869,9 +872,11 @@ export default {
|
||||
{
|
||||
hid: 'description',
|
||||
name: 'description',
|
||||
content: `${this.project.description} - Download the Minecraft ${
|
||||
content: `${
|
||||
this.project.description
|
||||
} - Download the Minecraft ${this.$formatProjectType(
|
||||
this.projectTypeDisplay
|
||||
} ${this.project.title} by ${
|
||||
)} ${this.project.title} by ${
|
||||
this.members.find((x) => x.role === 'Owner').user.username
|
||||
} on Modrinth`,
|
||||
},
|
||||
|
||||
@@ -209,7 +209,8 @@
|
||||
<section
|
||||
v-if="
|
||||
project.project_type !== 'resourcepack' &&
|
||||
project.project_type !== 'shader'
|
||||
project.project_type !== 'shader' &&
|
||||
project.project_type !== 'datapack'
|
||||
"
|
||||
class="card game-sides"
|
||||
>
|
||||
@@ -833,6 +834,9 @@ export default {
|
||||
this.newProject.client_side = this.clientSideType.toLowerCase()
|
||||
this.newProject.server_side = this.serverSideType.toLowerCase()
|
||||
|
||||
this.newProject.client_side = this.clientSideType.toLowerCase()
|
||||
this.newProject.server_side = this.serverSideType.toLowerCase()
|
||||
|
||||
this.$emit('update:project', this.newProject)
|
||||
|
||||
this.isEditing = false
|
||||
|
||||
@@ -371,7 +371,10 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', this._keyListener.bind(this))
|
||||
// eslint-disable-next-line nuxt/no-env-in-hooks
|
||||
if (process.client) {
|
||||
document.addEventListener('keydown', this._keyListener.bind(this))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showPreviewImage(files, index) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div v-if="version" class="version-page">
|
||||
<ModalConfirm
|
||||
v-if="$auth.user && currentMember"
|
||||
ref="modal_confirm"
|
||||
title="Are you sure you want to delete this version?"
|
||||
description="This will remove this version forever (like really forever)."
|
||||
@@ -14,6 +15,58 @@
|
||||
:item-id="version.id"
|
||||
item-type="version"
|
||||
/>
|
||||
<Modal
|
||||
v-if="$auth.user && currentMember"
|
||||
ref="modal_package_mod"
|
||||
header="Package data pack"
|
||||
>
|
||||
<div class="modal-package-mod universal-labels">
|
||||
<div class="markdown-body">
|
||||
<p>
|
||||
Package your data pack as a mod. This will create a new version with
|
||||
support for the selected mod loaders. You will be redirected to the
|
||||
new version and can edit it to your liking.
|
||||
</p>
|
||||
</div>
|
||||
<label for="package-mod-loaders">
|
||||
<span class="label__title">Mod loaders</span>
|
||||
<span class="label__description">
|
||||
The mod loaders you would like to package your data pack for.
|
||||
</span>
|
||||
</label>
|
||||
<multiselect
|
||||
id="package-mod-loaders"
|
||||
v-model="packageLoaders"
|
||||
:options="['fabric', 'forge', 'quilt']"
|
||||
:custom-label="
|
||||
(value) => value.charAt(0).toUpperCase() + value.slice(1)
|
||||
"
|
||||
:multiple="true"
|
||||
:searchable="false"
|
||||
:show-no-results="false"
|
||||
:show-labels="false"
|
||||
placeholder="Choose loaders.."
|
||||
open-direction="top"
|
||||
/>
|
||||
<div class="button-group">
|
||||
<button
|
||||
class="iconified-button"
|
||||
@click="$refs.modal_package_mod.hide()"
|
||||
>
|
||||
<CrossIcon />
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
class="iconified-button brand-button"
|
||||
:disabled="!$nuxt.$loading"
|
||||
@click="createDataPackVersion"
|
||||
>
|
||||
<RightArrowIcon />
|
||||
Begin packaging data pack
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<div class="version-page__title universal-card">
|
||||
<div class="version-header">
|
||||
<template v-if="isEditing">
|
||||
@@ -143,7 +196,7 @@
|
||||
Back to list
|
||||
</nuxt-link>
|
||||
<button
|
||||
v-if="$auth.user"
|
||||
v-if="$auth.user && !currentMember"
|
||||
class="iconified-button"
|
||||
@click="$refs.modal_version_report.show()"
|
||||
>
|
||||
@@ -164,6 +217,19 @@
|
||||
<EditIcon aria-hidden="true" />
|
||||
Edit
|
||||
</nuxt-link>
|
||||
<button
|
||||
v-if="
|
||||
currentMember &&
|
||||
version.loaders.some((x) =>
|
||||
$tag.loaderData.dataPackLoaders.includes(x)
|
||||
)
|
||||
"
|
||||
class="iconified-button"
|
||||
@click="$refs.modal_package_mod.show()"
|
||||
>
|
||||
<BoxIcon aria-hidden="true" />
|
||||
Package as mod
|
||||
</button>
|
||||
<button
|
||||
v-if="currentMember"
|
||||
class="iconified-button danger-button"
|
||||
@@ -222,7 +288,10 @@
|
||||
></div>
|
||||
</div>
|
||||
<div
|
||||
v-if="version.dependencies.length > 0 || isEditing"
|
||||
v-if="
|
||||
version.dependencies.length > 0 ||
|
||||
(isEditing && project.project_type !== 'modpack')
|
||||
"
|
||||
class="version-page__dependencies universal-card"
|
||||
>
|
||||
<h3>Dependencies</h3>
|
||||
@@ -269,7 +338,7 @@
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
v-if="isEditing"
|
||||
v-if="isEditing && project.project_type !== 'modpack'"
|
||||
class="iconified-button"
|
||||
@click="version.dependencies.splice(index, 1)"
|
||||
>
|
||||
@@ -308,7 +377,7 @@
|
||||
:searchable="false"
|
||||
:close-on-select="true"
|
||||
:show-labels="false"
|
||||
:allow-empty="false"
|
||||
:allow-empty="true"
|
||||
/>
|
||||
<input
|
||||
v-model="newDependencyId"
|
||||
@@ -334,7 +403,7 @@
|
||||
:searchable="false"
|
||||
:close-on-select="true"
|
||||
:show-labels="false"
|
||||
:allow-empty="false"
|
||||
:allow-empty="true"
|
||||
/>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
@@ -385,7 +454,48 @@
|
||||
<span class="filename">
|
||||
<strong>{{ file.filename }}</strong>
|
||||
<span class="file-size">({{ $formatBytes(file.size) }})</span>
|
||||
<span
|
||||
v-if="primaryFile.hashes.sha1 === file.hashes.sha1"
|
||||
class="file-type"
|
||||
>
|
||||
Primary
|
||||
</span>
|
||||
<span
|
||||
v-else-if="
|
||||
file.file_type === 'required-resource-pack' && !isEditing
|
||||
"
|
||||
class="file-type"
|
||||
>
|
||||
Required resource pack
|
||||
</span>
|
||||
<span
|
||||
v-else-if="
|
||||
file.file_type === 'optional-resource-pack' && !isEditing
|
||||
"
|
||||
class="file-type"
|
||||
>
|
||||
Optional resource pack
|
||||
</span>
|
||||
</span>
|
||||
<multiselect
|
||||
v-if="
|
||||
version.loaders.some((x) =>
|
||||
$tag.loaderData.dataPackLoaders.includes(x)
|
||||
) &&
|
||||
isEditing &&
|
||||
primaryFile.hashes.sha1 !== file.hashes.sha1
|
||||
"
|
||||
v-model="oldFileTypes[index]"
|
||||
class="raised-multiselect"
|
||||
placeholder="Select file type"
|
||||
:options="fileTypes"
|
||||
track-by="value"
|
||||
label="display"
|
||||
:searchable="false"
|
||||
:close-on-select="true"
|
||||
:show-labels="false"
|
||||
:allow-empty="false"
|
||||
/>
|
||||
<FileInput
|
||||
v-if="isEditing && primaryFile.hashes.sha1 === file.hashes.sha1"
|
||||
class="iconified-button raised-button"
|
||||
@@ -397,6 +507,8 @@
|
||||
(x) => {
|
||||
deleteFiles.push(file.hashes.sha1)
|
||||
version.files.splice(index, 1)
|
||||
oldFileTypes.splice(index, 1)
|
||||
|
||||
replaceFile = x[0]
|
||||
}
|
||||
"
|
||||
@@ -409,6 +521,7 @@
|
||||
@click="
|
||||
deleteFiles.push(file.hashes.sha1)
|
||||
version.files.splice(index, 1)
|
||||
oldFileTypes.splice(index, 1)
|
||||
"
|
||||
>
|
||||
<TrashIcon />
|
||||
@@ -432,9 +545,29 @@
|
||||
<strong>{{ file.name }}</strong>
|
||||
<span class="file-size">({{ $formatBytes(file.size) }})</span>
|
||||
</span>
|
||||
<multiselect
|
||||
v-if="
|
||||
version.loaders.some((x) =>
|
||||
$tag.loaderData.dataPackLoaders.includes(x)
|
||||
)
|
||||
"
|
||||
v-model="newFileTypes[index]"
|
||||
class="raised-multiselect"
|
||||
placeholder="Select file type"
|
||||
:options="fileTypes"
|
||||
track-by="value"
|
||||
label="display"
|
||||
:searchable="false"
|
||||
:close-on-select="true"
|
||||
:show-labels="false"
|
||||
:allow-empty="false"
|
||||
/>
|
||||
<button
|
||||
class="iconified-button raised-button"
|
||||
@click="newFiles.splice(index, 1)"
|
||||
@click="
|
||||
newFiles.splice(index, 1)
|
||||
newFileTypes.splice(index, 1)
|
||||
"
|
||||
>
|
||||
<TrashIcon />
|
||||
Remove
|
||||
@@ -442,14 +575,29 @@
|
||||
</div>
|
||||
<div class="additional-files">
|
||||
<h4>Upload additional files</h4>
|
||||
<span>Used for files such as sources or Javadocs.</span>
|
||||
<span
|
||||
v-if="
|
||||
version.loaders.some((x) =>
|
||||
$tag.loaderData.dataPackLoaders.includes(x)
|
||||
)
|
||||
"
|
||||
>
|
||||
Used for additional files such as required/optional resource packs
|
||||
</span>
|
||||
<span v-else>Used for files such as sources or Javadocs.</span>
|
||||
<FileInput
|
||||
prompt="Drag and drop to upload or click to select"
|
||||
multiple
|
||||
long-style
|
||||
:accept="acceptFileFromProjectType(project.project_type)"
|
||||
:max-size="524288000"
|
||||
@change="(x) => x.forEach((y) => newFiles.push(y))"
|
||||
@change="
|
||||
(x) =>
|
||||
x.forEach((y) => {
|
||||
newFiles.push(y)
|
||||
newFileTypes.push(null)
|
||||
})
|
||||
"
|
||||
>
|
||||
<UploadIcon />
|
||||
</FileInput>
|
||||
@@ -629,6 +777,7 @@ import Multiselect from 'vue-multiselect'
|
||||
import {
|
||||
acceptFileFromProjectType,
|
||||
inferVersionInfo,
|
||||
createDataPackVersion,
|
||||
} from '~/plugins/fileUtils'
|
||||
|
||||
import VersionBadge from '~/components/ui/Badge'
|
||||
@@ -654,9 +803,13 @@ import PlusIcon from '~/assets/images/utils/plus.svg?inline'
|
||||
import TransferIcon from '~/assets/images/utils/transfer.svg?inline'
|
||||
import UploadIcon from '~/assets/images/utils/upload.svg?inline'
|
||||
import BackIcon from '~/assets/images/utils/left-arrow.svg?inline'
|
||||
import BoxIcon from '~/assets/images/utils/box.svg?inline'
|
||||
import RightArrowIcon from '~/assets/images/utils/right-arrow.svg?inline'
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Modal,
|
||||
FileInput,
|
||||
Checkbox,
|
||||
Chips,
|
||||
@@ -680,6 +833,8 @@ export default {
|
||||
ModalConfirm,
|
||||
ModalReport,
|
||||
Multiselect,
|
||||
BoxIcon,
|
||||
RightArrowIcon,
|
||||
},
|
||||
props: {
|
||||
project: {
|
||||
@@ -722,6 +877,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
primaryFile: {},
|
||||
alternateFile: {},
|
||||
version: {},
|
||||
|
||||
isEditing: false,
|
||||
@@ -738,6 +894,21 @@ export default {
|
||||
deleteFiles: [],
|
||||
replaceFile: null,
|
||||
|
||||
newFileTypes: [],
|
||||
oldFileTypes: [],
|
||||
fileTypes: [
|
||||
{
|
||||
display: 'Required resource pack',
|
||||
value: 'required-resource-pack',
|
||||
},
|
||||
{
|
||||
display: 'Optional resource pack',
|
||||
value: 'optional-resource-pack',
|
||||
},
|
||||
],
|
||||
|
||||
packageLoaders: ['forge', 'fabric', 'quilt'],
|
||||
|
||||
showKnownErrors: false,
|
||||
}
|
||||
},
|
||||
@@ -814,6 +985,7 @@ export default {
|
||||
acceptFileFromProjectType,
|
||||
reset() {
|
||||
this.primaryFile = {}
|
||||
this.alternateFile = {}
|
||||
this.version = {}
|
||||
|
||||
this.changelogViewMode = 'source'
|
||||
@@ -827,10 +999,14 @@ export default {
|
||||
this.newFiles = []
|
||||
this.deleteFiles = []
|
||||
this.replaceFile = null
|
||||
this.oldFileTypes = []
|
||||
this.newFileTypes = []
|
||||
|
||||
this.isEditing = false
|
||||
this.isCreating = false
|
||||
|
||||
this.packageLoaders = ['forge', 'fabric', 'quilt']
|
||||
|
||||
this.showKnownErrors = false
|
||||
},
|
||||
async setVersion() {
|
||||
@@ -916,6 +1092,9 @@ export default {
|
||||
this.version = JSON.parse(JSON.stringify(this.version))
|
||||
this.primaryFile =
|
||||
this.version.files.find((file) => file.primary) ?? this.version.files[0]
|
||||
this.alternateFile = this.version.files.find(
|
||||
(file) => file.file_type && file.file_type.includes('resource-pack')
|
||||
)
|
||||
|
||||
this.version.author_member = this.members.find(
|
||||
(x) => x.user.id === this.version.author_id
|
||||
@@ -948,6 +1127,10 @@ export default {
|
||||
}`
|
||||
: ''
|
||||
}
|
||||
|
||||
this.oldFileTypes = this.version.files.map((x) =>
|
||||
this.fileTypes.find((y) => y.value === x.file_type)
|
||||
)
|
||||
},
|
||||
async addDependency(
|
||||
dependencyAddMode,
|
||||
@@ -1037,12 +1220,24 @@ export default {
|
||||
|
||||
if (this.newFiles.length > 0 || this.replaceFile) {
|
||||
const formData = new FormData()
|
||||
const fileParts = this.newFiles.map((f, idx) => `${f.name}-${idx}`)
|
||||
|
||||
formData.append('data', JSON.stringify({}))
|
||||
formData.append(
|
||||
'data',
|
||||
JSON.stringify({
|
||||
file_types: this.newFileTypes.reduce(
|
||||
(acc, x, i) => ({
|
||||
...acc,
|
||||
[fileParts[i]]: x ? x.value : null,
|
||||
}),
|
||||
{}
|
||||
),
|
||||
})
|
||||
)
|
||||
|
||||
for (let i = 0; i < this.newFiles.length; i++) {
|
||||
formData.append(
|
||||
this.newFiles[i].name.concat('-' + i),
|
||||
fileParts[i],
|
||||
new Blob([this.newFiles[i]]),
|
||||
this.newFiles[i].name
|
||||
)
|
||||
@@ -1079,6 +1274,13 @@ export default {
|
||||
loaders: this.version.loaders,
|
||||
primary_file: ['sha1', this.primaryFile.hashes.sha1],
|
||||
featured: this.version.featured,
|
||||
file_types: this.oldFileTypes.map((x, i) => {
|
||||
return {
|
||||
algorithm: 'sha1',
|
||||
hash: this.version.files[i].hashes.sha1,
|
||||
file_type: x ? x.value : null,
|
||||
}
|
||||
}),
|
||||
},
|
||||
this.$defaultHeaders()
|
||||
)
|
||||
@@ -1090,7 +1292,7 @@ export default {
|
||||
)
|
||||
}
|
||||
|
||||
const [versions, featuredVersions] = (
|
||||
const [versions, featuredVersions, dependencies] = (
|
||||
await Promise.all([
|
||||
this.$axios.get(
|
||||
`project/${this.version.project_id}/version`,
|
||||
@@ -1100,12 +1302,17 @@ export default {
|
||||
`project/${this.version.project_id}/version?featured=true`,
|
||||
this.$defaultHeaders()
|
||||
),
|
||||
this.$axios.get(
|
||||
`project/${this.version.project_id}/dependencies`,
|
||||
this.$defaultHeaders()
|
||||
),
|
||||
])
|
||||
).map((it) => it.data)
|
||||
|
||||
const newEditedVersions = this.$computeVersions(versions)
|
||||
this.$emit('update:versions', newEditedVersions)
|
||||
this.$emit('update:featuredVersions', featuredVersions)
|
||||
this.$emit('update:dependencies', dependencies)
|
||||
|
||||
await this.$router.replace(
|
||||
`/${this.project.project_type}/${
|
||||
@@ -1128,7 +1335,6 @@ export default {
|
||||
},
|
||||
async createVersion() {
|
||||
this.$nuxt.$loading.start()
|
||||
|
||||
if (this.fieldErrors) {
|
||||
this.showKnownErrors = true
|
||||
|
||||
@@ -1136,6 +1342,21 @@ export default {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await this.createVersionRaw(this.version)
|
||||
} catch (err) {
|
||||
this.$notify({
|
||||
group: 'main',
|
||||
title: 'An error occurred',
|
||||
text: err.response ? err.response.data.description : err,
|
||||
type: 'error',
|
||||
})
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' })
|
||||
}
|
||||
|
||||
this.$nuxt.$loading.finish()
|
||||
},
|
||||
async createVersionRaw(version) {
|
||||
const formData = new FormData()
|
||||
|
||||
const fileParts = this.newFiles.map((f, idx) => `${f.name}-${idx}`)
|
||||
@@ -1144,20 +1365,27 @@ export default {
|
||||
}
|
||||
|
||||
if (this.project.project_type === 'resourcepack') {
|
||||
this.version.loaders = ['minecraft']
|
||||
version.loaders = ['minecraft']
|
||||
}
|
||||
|
||||
const newVersion = {
|
||||
project_id: this.version.project_id,
|
||||
project_id: version.project_id,
|
||||
file_parts: fileParts,
|
||||
version_number: this.version.version_number,
|
||||
version_title: this.version.name || this.version.version_number,
|
||||
version_body: this.version.changelog,
|
||||
dependencies: this.version.dependencies,
|
||||
game_versions: this.version.game_versions,
|
||||
loaders: this.version.loaders,
|
||||
release_channel: this.version.version_type,
|
||||
featured: this.version.featured,
|
||||
version_number: version.version_number,
|
||||
version_title: version.name || version.version_number,
|
||||
version_body: version.changelog,
|
||||
dependencies: version.dependencies,
|
||||
game_versions: version.game_versions,
|
||||
loaders: version.loaders,
|
||||
release_channel: version.version_type,
|
||||
featured: version.featured,
|
||||
file_types: this.newFileTypes.reduce(
|
||||
(acc, x, i) => ({
|
||||
...acc,
|
||||
[fileParts[this.replaceFile ? i + 1 : i]]: x ? x.value : null,
|
||||
}),
|
||||
{}
|
||||
),
|
||||
}
|
||||
|
||||
formData.append('data', JSON.stringify(newVersion))
|
||||
@@ -1172,58 +1400,51 @@ export default {
|
||||
|
||||
for (let i = 0; i < this.newFiles.length; i++) {
|
||||
formData.append(
|
||||
fileParts[i],
|
||||
fileParts[this.replaceFile ? i + 1 : i],
|
||||
new Blob([this.newFiles[i]]),
|
||||
this.newFiles[i].name
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
const data = (
|
||||
await this.$axios({
|
||||
url: 'version',
|
||||
method: 'POST',
|
||||
data: formData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
Authorization: this.$auth.token,
|
||||
},
|
||||
})
|
||||
).data
|
||||
|
||||
const [versions, featuredVersions] = (
|
||||
await Promise.all([
|
||||
this.$axios.get(
|
||||
`project/${this.version.project_id}/version`,
|
||||
this.$defaultHeaders()
|
||||
),
|
||||
this.$axios.get(
|
||||
`project/${this.version.project_id}/version?featured=true`,
|
||||
this.$defaultHeaders()
|
||||
),
|
||||
])
|
||||
).map((it) => it.data)
|
||||
|
||||
const newCreatedVersions = this.$computeVersions(versions)
|
||||
this.$emit('update:versions', newCreatedVersions)
|
||||
this.$emit('update:featuredVersions', featuredVersions)
|
||||
|
||||
await this.$router.push(
|
||||
`/${this.project.project_type}/${
|
||||
this.project.slug ? this.project.slug : this.project.project_id
|
||||
}/version/${data.id}`
|
||||
)
|
||||
} catch (err) {
|
||||
this.$notify({
|
||||
group: 'main',
|
||||
title: 'An error occurred',
|
||||
text: err.response.data.description,
|
||||
type: 'error',
|
||||
const data = (
|
||||
await this.$axios({
|
||||
url: 'version',
|
||||
method: 'POST',
|
||||
data: formData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
Authorization: this.$auth.token,
|
||||
},
|
||||
})
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' })
|
||||
}
|
||||
).data
|
||||
|
||||
this.$nuxt.$loading.finish()
|
||||
const [versions, featuredVersions, dependencies] = (
|
||||
await Promise.all([
|
||||
this.$axios.get(
|
||||
`project/${this.version.project_id}/version`,
|
||||
this.$defaultHeaders()
|
||||
),
|
||||
this.$axios.get(
|
||||
`project/${this.version.project_id}/version?featured=true`,
|
||||
this.$defaultHeaders()
|
||||
),
|
||||
this.$axios.get(
|
||||
`project/${this.version.project_id}/dependencies`,
|
||||
this.$defaultHeaders()
|
||||
),
|
||||
])
|
||||
).map((it) => it.data)
|
||||
|
||||
const newCreatedVersions = this.$computeVersions(versions)
|
||||
this.$emit('update:versions', newCreatedVersions)
|
||||
this.$emit('update:featuredVersions', featuredVersions)
|
||||
this.$emit('update:dependencies', dependencies)
|
||||
|
||||
await this.$router.push(
|
||||
`/${this.project.project_type}/${
|
||||
this.project.slug ? this.project.slug : this.project.project_id
|
||||
}/version/${data.id}`
|
||||
)
|
||||
},
|
||||
async deleteVersion() {
|
||||
this.$nuxt.$loading.start()
|
||||
@@ -1238,6 +1459,56 @@ export default {
|
||||
)
|
||||
this.$nuxt.$loading.finish()
|
||||
},
|
||||
async createDataPackVersion() {
|
||||
this.$nuxt.$loading.start()
|
||||
try {
|
||||
const blob = await createDataPackVersion(
|
||||
this.project,
|
||||
this.version,
|
||||
this.primaryFile,
|
||||
this.members,
|
||||
this.$tag.gameVersions,
|
||||
this.packageLoaders
|
||||
)
|
||||
|
||||
this.newFiles = []
|
||||
this.newFileTypes = []
|
||||
this.replaceFile = new File(
|
||||
[blob],
|
||||
`${this.project.slug}-${this.version.version_number}.jar`
|
||||
)
|
||||
|
||||
await this.createVersionRaw({
|
||||
project_id: this.project.id,
|
||||
author_id: this.currentMember.user.id,
|
||||
name: this.version.name,
|
||||
version_number: `${this.version.version_number}+mod`,
|
||||
changelog: this.version.changelog,
|
||||
version_type: this.version.version_type,
|
||||
dependencies: this.version.dependencies,
|
||||
game_versions: this.version.game_versions,
|
||||
loaders: this.packageLoaders,
|
||||
featured: this.version.featured,
|
||||
})
|
||||
|
||||
this.$refs.modal_package_mod.hide()
|
||||
|
||||
this.$notify({
|
||||
group: 'main',
|
||||
title: 'Packaging Success',
|
||||
text: 'Your data pack was successfully packaged as a mod! Make sure to playtest to check for errors.',
|
||||
type: 'success',
|
||||
})
|
||||
} catch (err) {
|
||||
this.$notify({
|
||||
group: 'main',
|
||||
title: 'An error occurred',
|
||||
text: err.response ? err.response.data.description : err,
|
||||
type: 'error',
|
||||
})
|
||||
}
|
||||
this.$nuxt.$loading.finish()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -1383,8 +1654,7 @@ export default {
|
||||
}
|
||||
|
||||
.filename {
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: anywhere;
|
||||
word-wrap: anywhere;
|
||||
}
|
||||
|
||||
.file-size {
|
||||
@@ -1392,6 +1662,19 @@ export default {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.file-type {
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.raised-multiselect {
|
||||
display: none;
|
||||
margin: 0 0.5rem;
|
||||
height: 40px;
|
||||
max-height: 40px;
|
||||
min-width: 235px;
|
||||
}
|
||||
|
||||
.iconified-button {
|
||||
margin-left: auto;
|
||||
}
|
||||
@@ -1399,6 +1682,13 @@ export default {
|
||||
&:not(:nth-child(2)) {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
// TODO: Make file type editing work on mobile
|
||||
@media (min-width: 600px) {
|
||||
.raised-multiselect {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.additional-files {
|
||||
@@ -1454,4 +1744,23 @@ export default {
|
||||
.separator {
|
||||
margin: var(--spacing-card-sm) 0;
|
||||
}
|
||||
|
||||
.modal-package-mod {
|
||||
padding: var(--spacing-card-bg);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.markdown-body {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.multiselect {
|
||||
max-width: 20rem;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
margin-left: auto;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
<template>
|
||||
<div class="main">
|
||||
<div class="card">
|
||||
<h1>About</h1>
|
||||
<p>
|
||||
Founded in 2020, Modrinth was created to provide modders with an open
|
||||
and intuitive platform to publish their projects on.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Our primary goal is to be as open as possible, with all our code being
|
||||
<a :target="$external()" href="https://github.com/modrinth">
|
||||
open source</a
|
||||
>, while giving back to the modding community as much as possible.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
While we still are in beta, we hope we can be a major modding platform
|
||||
for all modders.
|
||||
</p>
|
||||
<h2>How does Modrinth work?</h2>
|
||||
<p>
|
||||
Modrinth is not just a website: it is made of several different
|
||||
components that all come together to make a fast and flexible modding
|
||||
platform.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
On the technical level, Modrinth is made up of two main components: the
|
||||
Rust-based backend named
|
||||
<a :target="$external()" href="https://github.com/modrinth/labrinth"
|
||||
>Labrinth</a
|
||||
>, and the Vue-based frontend named
|
||||
<a :target="$external()" href="https://github.com/modrinth/knossos">
|
||||
Knossos</a
|
||||
>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Additionally, some other custom-created resources exist, including but
|
||||
not limited to:
|
||||
<a :target="$external()" href="https://github.com/modrinth/minotaur"
|
||||
>Minotaur</a
|
||||
>, a Gradle plugin for easily publishing mods to Modrinth, and
|
||||
<a :target="$external()" href="https://github.com/modrinth/minos">
|
||||
Minos</a
|
||||
>, an authentication provider. All of Modrinth's code can be found on
|
||||
<a :target="$external()" href="https://github.com/modrinth"
|
||||
>our GitHub page</a
|
||||
>.
|
||||
</p>
|
||||
<h2>Backend Documentation</h2>
|
||||
<p>
|
||||
Documentation for the Modrinth API (Labrinth) can be found on the GitHub
|
||||
repository's wiki
|
||||
<a :target="$external()" href="https://docs.modrinth.com">here</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
auth: false,
|
||||
head: {
|
||||
title: 'About - Modrinth',
|
||||
meta: [
|
||||
{
|
||||
hid: 'apple-mobile-web-app-title',
|
||||
name: 'apple-mobile-web-app-title',
|
||||
content: 'About',
|
||||
},
|
||||
{
|
||||
hid: 'og:title',
|
||||
name: 'og:title',
|
||||
content: 'About',
|
||||
},
|
||||
{
|
||||
hid: 'og:url',
|
||||
name: 'og:url',
|
||||
content: `https://modrinth.com/about`,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.main {
|
||||
margin: var(--spacing-card-sm) auto;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: underline;
|
||||
color: var(--color-link);
|
||||
}
|
||||
</style>
|
||||
@@ -126,7 +126,7 @@
|
||||
<div class="title">
|
||||
<h3>
|
||||
{{ item.item_type }}
|
||||
<a :href="item.url">{{ item.item_id }}</a>
|
||||
<nuxt-link :to="item.url">{{ item.item_id }}</nuxt-link>
|
||||
</h3>
|
||||
reported by
|
||||
<a :href="`/user/${item.reporter}`">{{ item.reporter }}</a>
|
||||
|
||||
@@ -78,7 +78,9 @@
|
||||
</div>
|
||||
</section>
|
||||
<section
|
||||
v-if="projectType.id !== 'resourcepack'"
|
||||
v-if="
|
||||
projectType.id !== 'resourcepack' && projectType.id !== 'datapack'
|
||||
"
|
||||
aria-label="Loader filters"
|
||||
>
|
||||
<h3
|
||||
@@ -101,15 +103,15 @@
|
||||
x.name !== 'quilt'
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (projectType.id === 'mod' && showAllLoaders) {
|
||||
} else if (projectType.id === 'mod' && showAllLoaders) {
|
||||
return $tag.loaderData.modLoaders.includes(x.name)
|
||||
} else if (projectType.id === 'plugin') {
|
||||
return $tag.loaderData.pluginLoaders.includes(x.name)
|
||||
} else if (projectType.id === 'datapack') {
|
||||
return $tag.loaderData.dataPackLoaders.includes(x.name)
|
||||
} else {
|
||||
return x.supported_project_types.includes(projectType.actual)
|
||||
}
|
||||
|
||||
return projectType.id === 'plugin'
|
||||
? $tag.loaderData.pluginLoaders.includes(x.name)
|
||||
: x.supported_project_types.includes(projectType.actual)
|
||||
})"
|
||||
:key="loader.name"
|
||||
ref="loaderFilters"
|
||||
@@ -158,7 +160,9 @@
|
||||
</section>
|
||||
<section
|
||||
v-if="
|
||||
!['resourcepack', 'plugin', 'shader'].includes(projectType.id)
|
||||
!['resourcepack', 'plugin', 'shader', 'datapack'].includes(
|
||||
projectType.id
|
||||
)
|
||||
"
|
||||
aria-label="Environment filters"
|
||||
>
|
||||
@@ -376,6 +380,9 @@
|
||||
:categories="result.display_categories"
|
||||
:search="true"
|
||||
:show-updated-date="sortType.name !== 'newest'"
|
||||
:hide-loaders="
|
||||
['resourcepack', 'datapack'].includes(projectType.id)
|
||||
"
|
||||
/>
|
||||
<div v-if="results && results.length === 0" class="no-results">
|
||||
<p>No results found for your query!</p>
|
||||
@@ -714,6 +721,12 @@ export default {
|
||||
(x) => `categories:'${encodeURIComponent(x)}'`
|
||||
)
|
||||
)
|
||||
} else if (this.projectType.id === 'datapack') {
|
||||
formattedFacets.push(
|
||||
this.$tag.loaderData.dataPackLoaders.map(
|
||||
(x) => `categories:'${encodeURIComponent(x)}'`
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (this.selectedVersions.length > 0) {
|
||||
|
||||
11
pages/search/datapacks.vue
Normal file
11
pages/search/datapacks.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Datapacks',
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -161,6 +161,7 @@ export default {
|
||||
resourcepack: 'gallery',
|
||||
modpack: 'list',
|
||||
shader: 'gallery',
|
||||
datapack: 'list',
|
||||
user: 'list',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
},
|
||||
...projectTypes.map((x) => {
|
||||
return {
|
||||
label: x === 'resourcepack' ? 'Resource Packs' : x + 's',
|
||||
label: $formatProjectType(x) + 's',
|
||||
href: x,
|
||||
}
|
||||
}),
|
||||
@@ -326,13 +326,47 @@ export default {
|
||||
}
|
||||
|
||||
let gitHubUser = {}
|
||||
|
||||
let versions = []
|
||||
try {
|
||||
gitHubUser = (
|
||||
await data.$axios.get(`https://api.github.com/user/` + user.github_id)
|
||||
).data
|
||||
const [gitHubUserData, versionsData] = (
|
||||
await Promise.all([
|
||||
data.$axios.get(`https://api.github.com/user/` + user.github_id),
|
||||
data.$axios.get(
|
||||
`versions?ids=${JSON.stringify(
|
||||
[].concat.apply(
|
||||
[],
|
||||
projects.map((x) => x.versions)
|
||||
)
|
||||
)}`
|
||||
),
|
||||
])
|
||||
).map((it) => it.data)
|
||||
gitHubUser = gitHubUserData
|
||||
versions = versionsData
|
||||
} catch {}
|
||||
|
||||
for (const version of versions) {
|
||||
const projectIndex = projects.findIndex(
|
||||
(x) => x.id === version.project_id
|
||||
)
|
||||
if (projects[projectIndex].loaders) {
|
||||
for (const loader of version.loaders) {
|
||||
if (!projects[projectIndex].loaders.includes(loader)) {
|
||||
projects[projectIndex].loaders.push(loader)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
projects[projectIndex].loaders = version.loaders
|
||||
}
|
||||
}
|
||||
for (const project of projects) {
|
||||
project.categories = project.categories.concat(project.loaders)
|
||||
project.project_type = data.$getProjectTypeForUrl(
|
||||
project.project_type,
|
||||
project.categories
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
projects,
|
||||
|
||||
@@ -15,7 +15,6 @@ import { formatBytes } from '~/plugins/shorthands'
|
||||
export const fileIsValid = (file, validationOptions) => {
|
||||
const { maxSize, alertOnInvalid } = validationOptions
|
||||
if (maxSize !== null && maxSize !== undefined && file.size > maxSize) {
|
||||
console.log(`File size: ${file.size}, max size: ${maxSize}`)
|
||||
if (alertOnInvalid) {
|
||||
alert(
|
||||
`File ${file.name} is too big! Must be less than ${formatBytes(
|
||||
@@ -39,6 +38,8 @@ export const acceptFileFromProjectType = (projectType) => {
|
||||
return '.zip,application/zip'
|
||||
case 'shader':
|
||||
return '.zip,application/zip'
|
||||
case 'datapack':
|
||||
return '.zip,application/zip'
|
||||
case 'modpack':
|
||||
return '.mrpack,application/x-modrinth-modpack+zip'
|
||||
default:
|
||||
@@ -108,7 +109,7 @@ export const inferVersionInfo = async function (
|
||||
'META-INF/mods.toml': (file, zip) => {
|
||||
const metadata = TOML.parse(file)
|
||||
|
||||
console.log(JSON.stringify(metadata))
|
||||
// ${file.jarVersion} -> Implementation-Version from manifest
|
||||
|
||||
// TODO: Parse minecraft version ranges, handle if version is set to value from manifest
|
||||
if (metadata.mods && metadata.mods.length > 0) {
|
||||
@@ -165,8 +166,10 @@ export const inferVersionInfo = async function (
|
||||
version_type: versionType(metadata.quilt_loader.version),
|
||||
game_versions: metadata.quilt_loader.depends
|
||||
? gameVersionRange(
|
||||
metadata.depends.find((x) => x.id === 'minecraft')
|
||||
? metadata.depends.find((x) => x.id === 'minecraft').versions
|
||||
metadata.quilt_loader.depends.find((x) => x.id === 'minecraft')
|
||||
? metadata.quilt_loader.depends.find(
|
||||
(x) => x.id === 'minecraft'
|
||||
).versions
|
||||
: [],
|
||||
gameVersions
|
||||
)
|
||||
@@ -222,6 +225,112 @@ export const inferVersionInfo = async function (
|
||||
.map((x) => x.version),
|
||||
}
|
||||
},
|
||||
// Resource Packs + Data Packs
|
||||
'pack.mcmeta': (file) => {
|
||||
const metadata = JSON.parse(file)
|
||||
|
||||
function getRange(versionA, versionB) {
|
||||
const startingIndex = gameVersions.findIndex(
|
||||
(x) => x.version === versionA
|
||||
)
|
||||
const endingIndex = gameVersions.findIndex(
|
||||
(x) => x.version === versionB
|
||||
)
|
||||
|
||||
const final = []
|
||||
const filterOnlyRelease =
|
||||
gameVersions[startingIndex].version_type === 'release'
|
||||
|
||||
for (let i = startingIndex; i >= endingIndex; i--) {
|
||||
if (
|
||||
gameVersions[i].version_type === 'release' ||
|
||||
!filterOnlyRelease
|
||||
) {
|
||||
final.push(gameVersions[i].version)
|
||||
}
|
||||
}
|
||||
|
||||
return final
|
||||
}
|
||||
|
||||
const loaders = []
|
||||
let newGameVersions = []
|
||||
|
||||
if (project.actualProjectType === 'mod') {
|
||||
loaders.push('datapack')
|
||||
|
||||
switch (metadata.pack.pack_format) {
|
||||
case 4:
|
||||
newGameVersions = getRange('1.13', '1.14.4')
|
||||
break
|
||||
case 5:
|
||||
newGameVersions = getRange('1.15', '1.16.1')
|
||||
break
|
||||
case 6:
|
||||
newGameVersions = getRange('1.16.2', '1.16.5')
|
||||
break
|
||||
case 7:
|
||||
newGameVersions = getRange('1.17', '1.17.1')
|
||||
break
|
||||
case 8:
|
||||
newGameVersions = getRange('1.18', '1.18.1')
|
||||
break
|
||||
case 9:
|
||||
newGameVersions.push('1.18.2')
|
||||
break
|
||||
case 10:
|
||||
newGameVersions = getRange('1.19', '1.19.3')
|
||||
break
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
if (project.actualProjectType === 'resourcepack') {
|
||||
loaders.push('minecraft')
|
||||
|
||||
switch (metadata.pack.pack_format) {
|
||||
case 1:
|
||||
newGameVersions = getRange('1.6.1', '1.8.9')
|
||||
break
|
||||
case 2:
|
||||
newGameVersions = getRange('1.9', '1.10.2')
|
||||
break
|
||||
case 3:
|
||||
newGameVersions = getRange('1.11', '1.12.2')
|
||||
break
|
||||
case 4:
|
||||
newGameVersions = getRange('1.13', '1.14.4')
|
||||
break
|
||||
case 5:
|
||||
newGameVersions = getRange('1.15', '1.16.1')
|
||||
break
|
||||
case 6:
|
||||
newGameVersions = getRange('1.16.2', '1.16.5')
|
||||
break
|
||||
case 7:
|
||||
newGameVersions = getRange('1.17', '1.17.1')
|
||||
break
|
||||
case 8:
|
||||
newGameVersions = getRange('1.18', '1.18.2')
|
||||
break
|
||||
case 9:
|
||||
newGameVersions = getRange('1.19', '1.19.2')
|
||||
break
|
||||
case 11:
|
||||
newGameVersions = getRange('22w42a', '22w44a')
|
||||
break
|
||||
case 12:
|
||||
newGameVersions.push('1.19.3')
|
||||
break
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
loaders,
|
||||
game_versions: newGameVersions,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const zipReader = new JSZip()
|
||||
@@ -237,3 +346,201 @@ export const inferVersionInfo = async function (
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const createDataPackVersion = async function (
|
||||
project,
|
||||
version,
|
||||
primaryFile,
|
||||
members,
|
||||
allGameVersions,
|
||||
loaders
|
||||
) {
|
||||
// force version to start with number, as required by FML
|
||||
const newVersionNumber = version.version_number.match(/^\d/)
|
||||
? version.version_number
|
||||
: `1-${version.version_number}`
|
||||
|
||||
const newSlug = `${project.slug
|
||||
.replace('-', '_')
|
||||
.replace(/\W/g, '')
|
||||
.substring(0, 63)}_mr`
|
||||
|
||||
const iconPath = `${project.slug}_pack.png`
|
||||
|
||||
const fabricModJson = {
|
||||
schemaVersion: 1,
|
||||
id: newSlug,
|
||||
version: newVersionNumber,
|
||||
name: project.title,
|
||||
description: project.description,
|
||||
authors: members.map((x) => x.name),
|
||||
contact: {
|
||||
homepage: `${process.env.domain}/${project.project_type}/${
|
||||
project.slug ?? project.id
|
||||
}`,
|
||||
},
|
||||
license: project.license.id,
|
||||
icon: iconPath,
|
||||
environment: '*',
|
||||
depends: {
|
||||
'fabric-resource-loader-v0': '*',
|
||||
},
|
||||
}
|
||||
|
||||
const quiltModJson = {
|
||||
schema_version: 1,
|
||||
quilt_loader: {
|
||||
group: 'com.modrinth',
|
||||
id: newSlug,
|
||||
version: newVersionNumber,
|
||||
metadata: {
|
||||
name: project.title,
|
||||
description: project.description,
|
||||
contributors: members.reduce(
|
||||
(acc, x) => ({
|
||||
...acc,
|
||||
[x.name]: x.role,
|
||||
}),
|
||||
{}
|
||||
),
|
||||
contact: {
|
||||
homepage: `${process.env.domain}/${project.project_type}/${
|
||||
project.slug ?? project.id
|
||||
}`,
|
||||
},
|
||||
icon: iconPath,
|
||||
},
|
||||
intermediate_mappings: 'net.fabricmc:intermediary',
|
||||
depends: [
|
||||
{
|
||||
id: 'quilt_resource_loader',
|
||||
versions: '*',
|
||||
unless: 'fabric-resource-loader-v0',
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const cutoffIndex = allGameVersions.findIndex((x) => x.version === '1.18.2')
|
||||
|
||||
let maximumIndex = Number.MIN_VALUE
|
||||
for (const val of version.game_versions) {
|
||||
const index = allGameVersions.findIndex((x) => x.version === val)
|
||||
if (index > maximumIndex) {
|
||||
maximumIndex = index
|
||||
}
|
||||
}
|
||||
|
||||
const newForge = maximumIndex < cutoffIndex
|
||||
|
||||
const forgeModsToml = {
|
||||
modLoader: newForge ? 'lowcodefml' : 'javafml',
|
||||
loaderVersion: newForge ? '[40,)' : '[25,)',
|
||||
license: project.license.id,
|
||||
showAsResourcePack: true,
|
||||
mods: [
|
||||
{
|
||||
modId: newSlug,
|
||||
version: newVersionNumber,
|
||||
displayName: project.title,
|
||||
description: project.description,
|
||||
logoFile: iconPath,
|
||||
updateJSONURL: `${process.env.authURLBase.replace(
|
||||
'/v2/',
|
||||
''
|
||||
)}/updates/${project.id}/forge_updates.json`,
|
||||
credits: 'Generated by Modrinth',
|
||||
authors: members.map((x) => x.name).join(', '),
|
||||
displayURL: `${process.env.domain}/${project.project_type}/${
|
||||
project.slug ?? project.id
|
||||
}`,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
if (project.source_url) {
|
||||
quiltModJson.quilt_loader.metadata.contact.sources = project.source_url
|
||||
fabricModJson.contact.sources = project.source_url
|
||||
}
|
||||
|
||||
if (project.issues_url) {
|
||||
quiltModJson.quilt_loader.metadata.contact.issues = project.issues_url
|
||||
fabricModJson.contact.issues = project.issues_url
|
||||
forgeModsToml.issueTrackerURL = project.issues_url
|
||||
}
|
||||
|
||||
const primaryFileData = await (await fetch(primaryFile.url)).blob()
|
||||
|
||||
const primaryZipReader = new JSZip()
|
||||
await primaryZipReader.loadAsync(primaryFileData)
|
||||
|
||||
if (loaders.includes('fabric'))
|
||||
primaryZipReader.file('fabric.mod.json', JSON.stringify(fabricModJson))
|
||||
if (loaders.includes('quilt'))
|
||||
primaryZipReader.file('quilt.mod.json', JSON.stringify(quiltModJson))
|
||||
if (loaders.includes('forge'))
|
||||
primaryZipReader.file('META-INF/mods.toml', TOML.stringify(forgeModsToml))
|
||||
|
||||
if (!newForge && loaders.includes('forge')) {
|
||||
const classFile = new Uint8Array(
|
||||
await (
|
||||
await fetch(
|
||||
'https://cdn.modrinth.com/wrapper/ModrinthWrapperRestiched.class'
|
||||
)
|
||||
).arrayBuffer()
|
||||
)
|
||||
|
||||
let binary = ''
|
||||
for (let i = 0; i < classFile.byteLength; i++) {
|
||||
binary += String.fromCharCode(classFile[i])
|
||||
}
|
||||
|
||||
binary = binary
|
||||
.replace(
|
||||
String.fromCharCode(32) + 'needs1to1be1changed1modrinth1mod',
|
||||
String.fromCharCode(newSlug.length) + newSlug
|
||||
)
|
||||
.replace('/wrappera/', `/${project.id.substring(0, 8)}/`)
|
||||
|
||||
const newArr = []
|
||||
for (let i = 0; i < binary.length; i++) {
|
||||
newArr.push(binary.charCodeAt(i))
|
||||
}
|
||||
|
||||
primaryZipReader.file(
|
||||
`com/modrinth/${project.id.substring(0, 8)}/ModrinthWrapper.class`,
|
||||
new Uint8Array(newArr)
|
||||
)
|
||||
}
|
||||
|
||||
const resourcePack = version.files.find(
|
||||
(x) => x.file_type === 'required-resource-pack'
|
||||
)
|
||||
|
||||
const resourcePackData = resourcePack
|
||||
? await (await fetch(resourcePack.url)).blob()
|
||||
: null
|
||||
|
||||
if (resourcePackData) {
|
||||
const resourcePackReader = new JSZip()
|
||||
await resourcePackReader.loadAsync(resourcePackData)
|
||||
|
||||
for (const [path, file] of Object.entries(resourcePackReader.files)) {
|
||||
if (!primaryZipReader.file(path) && !path.includes('.mcassetsroot')) {
|
||||
primaryZipReader.file(path, await file.async('uint8array'))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (primaryZipReader.file('pack.png')) {
|
||||
primaryZipReader.file(
|
||||
iconPath,
|
||||
await primaryZipReader.file('pack.png').async('uint8array')
|
||||
)
|
||||
}
|
||||
|
||||
return await primaryZipReader.generateAsync({
|
||||
type: 'blob',
|
||||
mimeType: 'application/java-archive',
|
||||
})
|
||||
}
|
||||
|
||||
@@ -153,24 +153,46 @@ export default (ctx, inject) => {
|
||||
const isMod = categories.some((category) => {
|
||||
return ctx.store.state.tag.loaderData.modLoaders.includes(category)
|
||||
})
|
||||
return isPlugin && isMod ? 'mod and plugin' : isPlugin ? 'plugin' : 'mod'
|
||||
} else {
|
||||
return formatProjectType(type)
|
||||
const isDataPack = categories.some((category) => {
|
||||
return ctx.store.state.tag.loaderData.dataPackLoaders.includes(category)
|
||||
})
|
||||
|
||||
if (isMod && isPlugin && isDataPack) {
|
||||
return 'mod, plugin, and data pack'
|
||||
} else if (isMod && isPlugin) {
|
||||
return 'mod and plugin'
|
||||
} else if (isMod && isDataPack) {
|
||||
return 'mod and datapack'
|
||||
}
|
||||
}
|
||||
|
||||
return type
|
||||
})
|
||||
inject('getProjectTypeForUrl', (type, categories) => {
|
||||
if (type === 'mod') {
|
||||
const isMod = categories.some((category) => {
|
||||
return ctx.store.state.tag.loaderData.modLoaders.includes(category)
|
||||
})
|
||||
|
||||
const isPlugin = categories.some((category) => {
|
||||
return ctx.store.state.tag.loaderData.allPluginLoaders.includes(
|
||||
category
|
||||
)
|
||||
})
|
||||
|
||||
const isMod = categories.some((category) => {
|
||||
return ctx.store.state.tag.loaderData.modLoaders.includes(category)
|
||||
const isDataPack = categories.some((category) => {
|
||||
return ctx.store.state.tag.loaderData.dataPackLoaders.includes(category)
|
||||
})
|
||||
|
||||
return isPlugin && isMod ? 'mod' : isPlugin ? 'plugin' : 'mod'
|
||||
if (isDataPack) {
|
||||
return 'datapack'
|
||||
} else if (isPlugin) {
|
||||
return 'plugin'
|
||||
} else if (isMod) {
|
||||
return 'mod'
|
||||
} else {
|
||||
return 'mod'
|
||||
}
|
||||
} else {
|
||||
return type
|
||||
}
|
||||
@@ -232,7 +254,10 @@ export const formatWallet = (name) => {
|
||||
export const formatProjectType = (name) => {
|
||||
if (name === 'resourcepack') {
|
||||
return 'Resource Pack'
|
||||
} else if (name === 'datapack') {
|
||||
return 'Data Pack'
|
||||
}
|
||||
|
||||
return capitalizeString(name)
|
||||
}
|
||||
|
||||
@@ -261,6 +286,8 @@ export const formatCategory = (name) => {
|
||||
return 'Path Tracing'
|
||||
} else if (name === 'pbr') {
|
||||
return 'PBR'
|
||||
} else if (name === 'datapack') {
|
||||
return 'Data pack'
|
||||
}
|
||||
|
||||
return capitalizeString(name)
|
||||
|
||||
@@ -19,6 +19,7 @@ export const defaults = {
|
||||
resourcepack: 'gallery',
|
||||
modpack: 'list',
|
||||
shader: 'gallery',
|
||||
datapack: 'list',
|
||||
user: 'list',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -17,6 +17,11 @@ export const state = () => ({
|
||||
id: 'plugin',
|
||||
display: 'plugin',
|
||||
},
|
||||
{
|
||||
actual: 'mod',
|
||||
id: 'datapack',
|
||||
display: 'datapack',
|
||||
},
|
||||
{
|
||||
actual: 'resourcepack',
|
||||
id: 'resourcepack',
|
||||
@@ -46,6 +51,7 @@ export const state = () => ({
|
||||
'waterfall',
|
||||
'velocity',
|
||||
],
|
||||
dataPackLoaders: ['datapack'],
|
||||
modLoaders: ['forge', 'fabric', 'quilt', 'liteloader', 'modloader', 'rift'],
|
||||
},
|
||||
projectViewModes: ['list', 'grid', 'gallery'],
|
||||
|
||||
Reference in New Issue
Block a user