mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-12-16 11:41:50 +00:00
Proper mods ui
This commit is contained in:
parent
6fa2515d85
commit
4176621b05
BIN
res/ui/icons/mods.png
Normal file
BIN
res/ui/icons/mods.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
BIN
res/ui/icons/mods_white.png
Normal file
BIN
res/ui/icons/mods_white.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
@ -31,6 +31,7 @@
|
|||||||
@import "states/mobile_warning";
|
@import "states/mobile_warning";
|
||||||
@import "states/changelog";
|
@import "states/changelog";
|
||||||
@import "states/puzzle_menu";
|
@import "states/puzzle_menu";
|
||||||
|
@import "states/mods";
|
||||||
|
|
||||||
@import "ingame_hud/buildings_toolbar";
|
@import "ingame_hud/buildings_toolbar";
|
||||||
@import "ingame_hud/building_placer";
|
@import "ingame_hud/building_placer";
|
||||||
|
|||||||
@ -185,11 +185,14 @@
|
|||||||
.updateLabel {
|
.updateLabel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
transform: translateX(50%) rotate(-5deg);
|
transform: translateX(50%) rotate(-5deg);
|
||||||
color: #300bff;
|
color: #fff;
|
||||||
@include Heading;
|
@include PlainText;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@include S(right, 40px);
|
@include S(right, 40px);
|
||||||
@include S(bottom, 20px);
|
@include S(bottom, 20px);
|
||||||
|
background: $modsColor;
|
||||||
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
@include S(padding, 0, 5px, 1px, 5px);
|
||||||
|
|
||||||
@include InlineAnimation(1.3s ease-in-out infinite) {
|
@include InlineAnimation(1.3s ease-in-out infinite) {
|
||||||
50% {
|
50% {
|
||||||
@ -305,14 +308,36 @@
|
|||||||
@include S(padding-bottom, 10px);
|
@include S(padding-bottom, 10px);
|
||||||
@include S(border-radius, $globalBorderRadius);
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
|
||||||
h3 {
|
.header {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
@include S(margin-bottom, 10px);
|
@include S(margin-bottom, 10px);
|
||||||
|
|
||||||
|
.editMods {
|
||||||
|
margin-left: auto;
|
||||||
|
@include S(width, 20px);
|
||||||
|
@include S(height, 20px);
|
||||||
|
padding: 0;
|
||||||
|
opacity: 0.5;
|
||||||
|
background: transparent center center/ 80% no-repeat;
|
||||||
|
& {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("icons/edit_key.png") !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
@include Heading;
|
@include Heading;
|
||||||
|
color: $modsColor;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dlcHint {
|
.dlcHint {
|
||||||
@include SuperSmallText;
|
@include SuperSmallText;
|
||||||
@include S(margin-top, 10px);
|
@include S(margin-top, 10px);
|
||||||
|
@include S(width, 300px);
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr auto;
|
grid-template-columns: 1fr auto;
|
||||||
@ -326,6 +351,7 @@
|
|||||||
@include S(border-radius, $globalBorderRadius);
|
@include S(border-radius, $globalBorderRadius);
|
||||||
@include S(padding, 5px);
|
@include S(padding, 5px);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
@include PlainText;
|
||||||
@include S(margin-bottom, 5px);
|
@include S(margin-bottom, 5px);
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr auto auto;
|
grid-template-columns: 1fr auto auto;
|
||||||
@ -375,6 +401,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modeButtons {
|
.modeButtons {
|
||||||
@ -419,27 +446,33 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.importButton {
|
.outer {
|
||||||
@include S(margin-top, 15px);
|
@include S(margin-top, 15px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.importButton {
|
||||||
@include IncreasedClickArea(0px);
|
@include IncreasedClickArea(0px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.newGameButton {
|
.newGameButton {
|
||||||
@include IncreasedClickArea(0px);
|
@include IncreasedClickArea(0px);
|
||||||
@include S(margin-top, 15px);
|
|
||||||
@include S(margin-left, 15px);
|
@include S(margin-left, 15px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.playModeButton {
|
.modsButton {
|
||||||
@include IncreasedClickArea(0px);
|
@include IncreasedClickArea(0px);
|
||||||
@include S(margin-top, 15px);
|
|
||||||
@include S(margin-left, 15px);
|
@include S(margin-left, 15px);
|
||||||
}
|
|
||||||
|
|
||||||
.editModeButton {
|
@include S(width, 20px);
|
||||||
@include IncreasedClickArea(0px);
|
|
||||||
@include S(margin-top, 15px);
|
& {
|
||||||
@include S(margin-left, 15px);
|
/* @load-async */
|
||||||
|
background-image: uiResource("res/ui/icons/mods_white.png") !important;
|
||||||
|
}
|
||||||
|
background-position: center center;
|
||||||
|
background-size: D(15px);
|
||||||
|
background-color: $modsColor !important;
|
||||||
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
.savegames {
|
.savegames {
|
||||||
|
|||||||
131
src/css/states/mods.scss
Normal file
131
src/css/states/mods.scss
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#state_ModsState {
|
||||||
|
.mainContent {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .headerBar {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
> h1 {
|
||||||
|
justify-self: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openModsFolder {
|
||||||
|
background-color: $modsColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.noModSupport {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.steamLink {
|
||||||
|
@include S(height, 50px);
|
||||||
|
@include S(width, 220px);
|
||||||
|
background: #171a23 center center / contain no-repeat;
|
||||||
|
overflow: hidden;
|
||||||
|
display: block;
|
||||||
|
text-indent: -999em;
|
||||||
|
cursor: pointer;
|
||||||
|
@include S(margin-top, 30px);
|
||||||
|
pointer-events: all;
|
||||||
|
transition: all 0.12s ease-in;
|
||||||
|
transition-property: opacity, transform;
|
||||||
|
|
||||||
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modsStats {
|
||||||
|
@include PlainText;
|
||||||
|
color: $accentColorDark;
|
||||||
|
|
||||||
|
&.noMods {
|
||||||
|
@include S(width, 400px);
|
||||||
|
align-self: center;
|
||||||
|
justify-self: center;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
@include Text;
|
||||||
|
@include S(margin-top, 100px);
|
||||||
|
color: lighten($accentColorDark, 15);
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
@include S(margin-bottom, 15px);
|
||||||
|
content: "";
|
||||||
|
@include S(width, 50px);
|
||||||
|
@include S(height, 50px);
|
||||||
|
background-position: center center;
|
||||||
|
background-size: contain;
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
&::before {
|
||||||
|
/* @load-async */
|
||||||
|
background-image: uiResource("res/ui/icons/mods.png") !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modsList {
|
||||||
|
@include S(margin-top, 10px);
|
||||||
|
overflow-y: scroll;
|
||||||
|
pointer-events: all;
|
||||||
|
@include S(padding-right, 5px);
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
.mod {
|
||||||
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
background: $accentColorBright;
|
||||||
|
@include S(margin-bottom, 4px);
|
||||||
|
@include S(padding, 7px);
|
||||||
|
@include S(grid-gap, 5px);
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr D(100px) D(100px) D(100px);
|
||||||
|
|
||||||
|
.checkbox {
|
||||||
|
align-self: center;
|
||||||
|
justify-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainInfo {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.description {
|
||||||
|
@include SuperSmallText;
|
||||||
|
@include S(margin-top, 5px);
|
||||||
|
color: $accentColorDark;
|
||||||
|
}
|
||||||
|
.website {
|
||||||
|
text-transform: uppercase;
|
||||||
|
align-self: start;
|
||||||
|
@include SuperSmallText;
|
||||||
|
@include S(margin-top, 5px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.version,
|
||||||
|
.author {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
strong {
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: $accentColorDark;
|
||||||
|
@include SuperSmallText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,20 +15,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
display: grid;
|
display: flex;
|
||||||
@include S(min-width, 210px);
|
@include S(min-width, 210px);
|
||||||
@include S(max-width, 320px);
|
@include S(max-width, 320px);
|
||||||
@include S(grid-gap, 3px);
|
flex-direction: column;
|
||||||
grid-template-rows: auto auto auto auto auto 1fr;
|
|
||||||
|
|
||||||
@include StyleBelowWidth($layoutBreak) {
|
@include StyleBelowWidth($layoutBreak) {
|
||||||
grid-template-rows: 1fr 1fr;
|
display: grid;
|
||||||
grid-template-columns: auto auto;
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
@include S(grid-gap, 5px);
|
||||||
max-width: unset !important;
|
max-width: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
@include S(margin-bottom, 3px);
|
||||||
&::after {
|
&::after {
|
||||||
content: unset;
|
content: unset;
|
||||||
}
|
}
|
||||||
@ -37,15 +38,26 @@
|
|||||||
|
|
||||||
@include StyleBelowWidth($layoutBreak) {
|
@include StyleBelowWidth($layoutBreak) {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
height: D(30px) !important;
|
||||||
|
padding: D(5px) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.other {
|
.other {
|
||||||
@include S(margin-top, 10px);
|
|
||||||
align-self: end;
|
align-self: end;
|
||||||
|
margin-top: auto;
|
||||||
|
|
||||||
@include StyleBelowWidth($layoutBreak) {
|
@include StyleBelowWidth($layoutBreak) {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
@include S(grid-gap, 5px);
|
||||||
|
max-width: unset !important;
|
||||||
|
grid-column: 1 / 3;
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +81,30 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button.manageMods {
|
||||||
|
background-color: lighten($modsColor, 38);
|
||||||
|
color: $modsColor;
|
||||||
|
display: flex;
|
||||||
|
@include S(padding-right, 5px);
|
||||||
|
.newBadge {
|
||||||
|
color: #fff;
|
||||||
|
@include S(border-radius, $globalBorderRadius);
|
||||||
|
background: $modsColor;
|
||||||
|
margin-left: auto;
|
||||||
|
@include S(padding, 0, 3px, 0, 3px);
|
||||||
|
|
||||||
|
@include InlineAnimation(1.3s ease-in-out infinite) {
|
||||||
|
50% {
|
||||||
|
transform: rotate(0deg) scale(1.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: $colorGreenBright;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
button.privacy {
|
button.privacy {
|
||||||
@include S(margin-top, 4px);
|
@include S(margin-top, 4px);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,6 +38,7 @@ $colorRedBright: #ef5072;
|
|||||||
$colorOrangeBright: #ef9d50;
|
$colorOrangeBright: #ef9d50;
|
||||||
$themeColor: #393747;
|
$themeColor: #393747;
|
||||||
$ingameHudBg: rgba(#333438, 0.9);
|
$ingameHudBg: rgba(#333438, 0.9);
|
||||||
|
$modsColor: rgb(214, 60, 228);
|
||||||
|
|
||||||
$text3dColor: #f4ffff;
|
$text3dColor: #f4ffff;
|
||||||
|
|
||||||
|
|||||||
@ -37,6 +37,7 @@ import { LoginState } from "./states/login";
|
|||||||
import { WegameSplashState } from "./states/wegame_splash";
|
import { WegameSplashState } from "./states/wegame_splash";
|
||||||
import { MODS } from "./mods/modloader";
|
import { MODS } from "./mods/modloader";
|
||||||
import { MOD_SIGNALS } from "./mods/mod_signals";
|
import { MOD_SIGNALS } from "./mods/mod_signals";
|
||||||
|
import { ModsState } from "./states/mods";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import("./platform/achievement_provider").AchievementProviderInterface} AchievementProviderInterface
|
* @typedef {import("./platform/achievement_provider").AchievementProviderInterface} AchievementProviderInterface
|
||||||
@ -171,6 +172,7 @@ export class Application {
|
|||||||
ChangelogState,
|
ChangelogState,
|
||||||
PuzzleMenuState,
|
PuzzleMenuState,
|
||||||
LoginState,
|
LoginState,
|
||||||
|
ModsState,
|
||||||
];
|
];
|
||||||
|
|
||||||
for (let i = 0; i < states.length; ++i) {
|
for (let i = 0; i < states.length; ++i) {
|
||||||
|
|||||||
@ -16,11 +16,12 @@ registerMod(shapez => {
|
|||||||
super(
|
super(
|
||||||
app,
|
app,
|
||||||
{
|
{
|
||||||
authorContact: "tobias@tobspr.io",
|
website: "https://tobspr.io",
|
||||||
authorName: "tobspr",
|
author: "tobspr",
|
||||||
name: "Demo Mod",
|
name: "Demo Mod",
|
||||||
version: "1",
|
version: "1",
|
||||||
id: "demo-mod",
|
id: "demo-mod",
|
||||||
|
description: "A simple mod to demonstrate the capatibilities of the mod loader.",
|
||||||
},
|
},
|
||||||
modLoader
|
modLoader
|
||||||
);
|
);
|
||||||
@ -28,11 +29,11 @@ registerMod(shapez => {
|
|||||||
|
|
||||||
init() {
|
init() {
|
||||||
// Add some custom css
|
// Add some custom css
|
||||||
this.modInterface.registerCss(`
|
// this.modInterface.registerCss(`
|
||||||
* {
|
// * {
|
||||||
font-family: "Comic Sans", "Comic Sans MS", Tahoma !important;
|
// font-family: "Comic Sans", "Comic Sans MS", Tahoma !important;
|
||||||
}
|
// }
|
||||||
`);
|
// `);
|
||||||
|
|
||||||
// Replace a builtin sprite
|
// Replace a builtin sprite
|
||||||
["red", "green", "blue", "yellow", "purple", "cyan", "white"].forEach(color => {
|
["red", "green", "blue", "yellow", "purple", "cyan", "white"].forEach(color => {
|
||||||
|
|||||||
@ -12,8 +12,9 @@ export class Mod {
|
|||||||
* @param {object} metadata
|
* @param {object} metadata
|
||||||
* @param {string} metadata.name
|
* @param {string} metadata.name
|
||||||
* @param {string} metadata.version
|
* @param {string} metadata.version
|
||||||
* @param {string} metadata.authorName
|
* @param {string} metadata.author
|
||||||
* @param {string} metadata.authorContact
|
* @param {string} metadata.website
|
||||||
|
* @param {string} metadata.description
|
||||||
* @param {string} metadata.id
|
* @param {string} metadata.id
|
||||||
*
|
*
|
||||||
* @param {ModLoader} modLoader
|
* @param {ModLoader} modLoader
|
||||||
|
|||||||
@ -155,36 +155,22 @@ export class MainMenuState extends GameState {
|
|||||||
? `
|
? `
|
||||||
|
|
||||||
<div class="modsList">
|
<div class="modsList">
|
||||||
<h3>${T.mainMenu.mods.title}
|
<div class="header">
|
||||||
|
<h3>${T.mods.title}</h3>
|
||||||
</h3>
|
<button class="styledButton editMods"></button>
|
||||||
|
</div>
|
||||||
<div class="modsList">
|
<div class="modsList">
|
||||||
${MODS.mods
|
${MODS.mods
|
||||||
.map(mod => {
|
.map(mod => {
|
||||||
return `
|
return `
|
||||||
<div class="mod">
|
<div class="mod">${mod.metadata.name} @ v${mod.metadata.version}</div>
|
||||||
<span class="name">${mod.metadata.name}</span>
|
|
||||||
<span class="version">${T.mainMenu.mods.version.replace(
|
|
||||||
"<version>",
|
|
||||||
mod.metadata.version
|
|
||||||
)}</span>
|
|
||||||
<span class="author">${T.mainMenu.mods.author.replace(
|
|
||||||
"<author>",
|
|
||||||
mod.metadata.authorName
|
|
||||||
)}</span>
|
|
||||||
</div>
|
|
||||||
`;
|
`;
|
||||||
})
|
})
|
||||||
.join("")}
|
.join("")}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dlcHint">
|
<div class="dlcHint">
|
||||||
${T.mainMenu.modsWarningPuzzleDLC}
|
${T.mainMenu.mods.warningPuzzleDLC}
|
||||||
<button class="styledButton modsOpenFolder">${
|
|
||||||
T.mainMenu.mods.openFolder
|
|
||||||
}</button>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@ -381,7 +367,7 @@ export class MainMenuState extends GameState {
|
|||||||
".puzzleDlcPlayButton": this.onPuzzleModeButtonClicked,
|
".puzzleDlcPlayButton": this.onPuzzleModeButtonClicked,
|
||||||
".puzzleDlcGetButton": this.onPuzzleWishlistButtonClicked,
|
".puzzleDlcGetButton": this.onPuzzleWishlistButtonClicked,
|
||||||
".wegameDisclaimer > .rating": this.onWegameRatingClicked,
|
".wegameDisclaimer > .rating": this.onWegameRatingClicked,
|
||||||
".modsOpenFolder": this.openModsFolder,
|
".editMods": this.onModsClicked,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const key in clickHandling) {
|
for (const key in clickHandling) {
|
||||||
@ -430,6 +416,14 @@ export class MainMenuState extends GameState {
|
|||||||
this.trackClicks(playBtn, this.onPlayButtonClicked);
|
this.trackClicks(playBtn, this.onPlayButtonClicked);
|
||||||
buttonContainer.appendChild(importButtonElement);
|
buttonContainer.appendChild(importButtonElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mods
|
||||||
|
const modsBtn = makeButton(
|
||||||
|
this.htmlElement.querySelector(".mainContainer .outer"),
|
||||||
|
["modsButton", "styledButton"],
|
||||||
|
" "
|
||||||
|
);
|
||||||
|
this.trackClicks(modsBtn, this.onModsClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
onPuzzleModeButtonClicked(force = false) {
|
onPuzzleModeButtonClicked(force = false) {
|
||||||
@ -742,6 +736,12 @@ export class MainMenuState extends GameState {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onModsClicked() {
|
||||||
|
this.moveToState("ModsState", {
|
||||||
|
backToStateId: "MainMenuState",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
onContinueButtonClicked() {
|
onContinueButtonClicked() {
|
||||||
let latestLastUpdate = 0;
|
let latestLastUpdate = 0;
|
||||||
let latestInternalId;
|
let latestInternalId;
|
||||||
@ -763,14 +763,6 @@ export class MainMenuState extends GameState {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
openModsFolder() {
|
|
||||||
if (!G_IS_STANDALONE) {
|
|
||||||
this.dialogs.showWarning(T.global.error, T.mainMenu.mods.folderOnlyStandalone);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
getIPCRenderer().send("open-mods-folder");
|
|
||||||
}
|
|
||||||
|
|
||||||
onLeave() {
|
onLeave() {
|
||||||
this.dialogs.cleanup();
|
this.dialogs.cleanup();
|
||||||
}
|
}
|
||||||
|
|||||||
135
src/js/states/mods.js
Normal file
135
src/js/states/mods.js
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
import { THIRDPARTY_URLS } from "../core/config";
|
||||||
|
import { TextualGameState } from "../core/textual_game_state";
|
||||||
|
import { getIPCRenderer } from "../core/utils";
|
||||||
|
import { MODS } from "../mods/modloader";
|
||||||
|
import { T } from "../translations";
|
||||||
|
|
||||||
|
export class ModsState extends TextualGameState {
|
||||||
|
constructor() {
|
||||||
|
super("ModsState");
|
||||||
|
}
|
||||||
|
|
||||||
|
getStateHeaderTitle() {
|
||||||
|
return T.mods.title;
|
||||||
|
}
|
||||||
|
|
||||||
|
internalGetFullHtml() {
|
||||||
|
let headerHtml = `
|
||||||
|
<div class="headerBar">
|
||||||
|
<h1><button class="backButton"></button> ${this.getStateHeaderTitle()}</h1>
|
||||||
|
|
||||||
|
<div class="actions">
|
||||||
|
${
|
||||||
|
G_IS_STANDALONE || G_IS_DEV
|
||||||
|
? `<button class="styledButton openModsFolder">${T.mods.openFolder}</button>`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
return `
|
||||||
|
${headerHtml}
|
||||||
|
<div class="container">
|
||||||
|
${this.getInnerHTML()}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
getMainContentHTML() {
|
||||||
|
if (!G_IS_STANDALONE && !G_IS_DEV) {
|
||||||
|
return `
|
||||||
|
<div class="noModSupport">
|
||||||
|
|
||||||
|
<p>${T.mods.noModSupport}</p>
|
||||||
|
|
||||||
|
<a href="#" class="steamLink steam_2_npr" target="_blank">Get the shapez.io standalone!</a>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MODS.mods.length === 0) {
|
||||||
|
return `
|
||||||
|
|
||||||
|
<div class="modsStats noMods">
|
||||||
|
|
||||||
|
${T.mods.modsInfo}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let modsHtml = ``;
|
||||||
|
|
||||||
|
MODS.mods.forEach(mod => {
|
||||||
|
modsHtml += `
|
||||||
|
<div class="mod">
|
||||||
|
<div class="mainInfo">
|
||||||
|
<span class="name">${mod.metadata.name}</span>
|
||||||
|
<span class="description">${mod.metadata.description}</span>
|
||||||
|
<a class="website" href="${mod.metadata.website}" target="_blank">Website</a>
|
||||||
|
</div>
|
||||||
|
<span class="version"><strong>${T.mods.version}</strong>${mod.metadata.version}</span>
|
||||||
|
<span class="author"><strong>${T.mods.author}</strong>${mod.metadata.author}</span>
|
||||||
|
<div class="value checkbox checked">
|
||||||
|
<span class="knob"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
return `
|
||||||
|
|
||||||
|
<div class="modsStats">
|
||||||
|
${T.mods.modsInfo}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modsList">
|
||||||
|
${modsHtml}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
onEnter() {
|
||||||
|
const steamLink = this.htmlElement.querySelector(".steamLink");
|
||||||
|
if (steamLink) {
|
||||||
|
this.trackClicks(steamLink, this.onSteamLinkClicked);
|
||||||
|
}
|
||||||
|
const openModsFolder = this.htmlElement.querySelector(".openModsFolder");
|
||||||
|
if (openModsFolder) {
|
||||||
|
this.trackClicks(openModsFolder, this.openModsFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkboxes = this.htmlElement.querySelectorAll(".checkbox");
|
||||||
|
Array.from(checkboxes).forEach(checkbox => {
|
||||||
|
this.trackClicks(checkbox, this.showModTogglingComingSoon);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
showModTogglingComingSoon() {
|
||||||
|
this.dialogs.showWarning(T.mods.togglingComingSoon.title, T.mods.togglingComingSoon.description);
|
||||||
|
}
|
||||||
|
|
||||||
|
openModsFolder() {
|
||||||
|
if (!G_IS_STANDALONE) {
|
||||||
|
this.dialogs.showWarning(T.global.error, T.mods.folderOnlyStandalone);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getIPCRenderer().send("open-mods-folder");
|
||||||
|
}
|
||||||
|
|
||||||
|
onSteamLinkClicked() {
|
||||||
|
this.app.analytics.trackUiClick("mods_steam_link");
|
||||||
|
this.app.platformWrapper.openExternalLink(
|
||||||
|
THIRDPARTY_URLS.stanaloneCampaignLink + "/shapez_modsettings"
|
||||||
|
);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDefaultPreviousState() {
|
||||||
|
return "SettingsState";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -19,6 +19,8 @@ export class SettingsState extends TextualGameState {
|
|||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
${this.getCategoryButtonsHtml()}
|
${this.getCategoryButtonsHtml()}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
${
|
${
|
||||||
this.app.platformWrapper.getSupportsKeyboard()
|
this.app.platformWrapper.getSupportsKeyboard()
|
||||||
? `
|
? `
|
||||||
@ -28,6 +30,18 @@ export class SettingsState extends TextualGameState {
|
|||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
${
|
||||||
|
G_WEGAME_VERSION
|
||||||
|
? ""
|
||||||
|
: `
|
||||||
|
<button class="styledButton categoryButton manageMods">${T.mods.title}
|
||||||
|
<span class="newBadge">${T.settings.newBadge}</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
<div class="other">
|
<div class="other">
|
||||||
|
|
||||||
${
|
${
|
||||||
@ -131,6 +145,11 @@ export class SettingsState extends TextualGameState {
|
|||||||
|
|
||||||
this.htmlElement.querySelector(".category").classList.add("active");
|
this.htmlElement.querySelector(".category").classList.add("active");
|
||||||
this.htmlElement.querySelector(".categoryButton").classList.add("active");
|
this.htmlElement.querySelector(".categoryButton").classList.add("active");
|
||||||
|
|
||||||
|
const modsButton = this.htmlElement.querySelector(".manageMods");
|
||||||
|
if (modsButton) {
|
||||||
|
this.trackClicks(modsButton, this.onModsClicked, { preventDefault: false });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setActiveCategory(category) {
|
setActiveCategory(category) {
|
||||||
@ -196,4 +215,8 @@ export class SettingsState extends TextualGameState {
|
|||||||
onKeybindingsClicked() {
|
onKeybindingsClicked() {
|
||||||
this.moveToStateAddGoBack("KeybindingsState");
|
this.moveToStateAddGoBack("KeybindingsState");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onModsClicked() {
|
||||||
|
this.moveToStateAddGoBack("ModsState");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -126,15 +126,10 @@ mainMenu:
|
|||||||
puzzleDlcWishlist: Wishlist now!
|
puzzleDlcWishlist: Wishlist now!
|
||||||
puzzleDlcViewNow: View Dlc
|
puzzleDlcViewNow: View Dlc
|
||||||
|
|
||||||
modsWarningPuzzleDLC: >-
|
|
||||||
Playing the Puzzle DLC is not possible with mods. Please disable all mods to play the DLC.
|
|
||||||
|
|
||||||
mods:
|
mods:
|
||||||
title: Active Mods
|
title: Active Mods
|
||||||
author: by <author>
|
warningPuzzleDLC: >-
|
||||||
version: v<version>
|
Playing the Puzzle DLC is not possible with mods. Please disable all mods to play the DLC.
|
||||||
openFolder: Open Folder
|
|
||||||
folderOnlyStandalone: Opening the mod folder is only possible when running the standalone.
|
|
||||||
|
|
||||||
puzzleMenu:
|
puzzleMenu:
|
||||||
play: Play
|
play: Play
|
||||||
@ -1096,6 +1091,22 @@ storyRewards:
|
|||||||
desc: >-
|
desc: >-
|
||||||
You have reached the end of the demo version!
|
You have reached the end of the demo version!
|
||||||
|
|
||||||
|
mods:
|
||||||
|
title: Mods
|
||||||
|
|
||||||
|
author: Author
|
||||||
|
version: Version
|
||||||
|
openFolder: Open Mods Folder
|
||||||
|
folderOnlyStandalone: Opening the mod folder is only possible when running the standalone.
|
||||||
|
|
||||||
|
modsInfo: >-
|
||||||
|
To install and manage mods, copy them to the mods folder within the game directory. You can also use the 'Open Mods Folder' button on the top right.
|
||||||
|
noModSupport: You need the standalone version on Steam to install mods.
|
||||||
|
|
||||||
|
togglingComingSoon:
|
||||||
|
title: Coming Soon
|
||||||
|
description: Enabling or disabling mods is currently only possible by copying the mod file from or to the mods/ folder. However, being able to toggle them here is planned for a future update!
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
title: Settings
|
title: Settings
|
||||||
categories:
|
categories:
|
||||||
@ -1111,6 +1122,7 @@ settings:
|
|||||||
buildDate: Built <at-date>
|
buildDate: Built <at-date>
|
||||||
tickrateHz: <amount> Hz
|
tickrateHz: <amount> Hz
|
||||||
rangeSliderPercentage: <amount> %
|
rangeSliderPercentage: <amount> %
|
||||||
|
newBadge: New!
|
||||||
|
|
||||||
labels:
|
labels:
|
||||||
uiScale:
|
uiScale:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user