Basic concept for the EULA feature to demo how this will all work
This commit is contained in:
parent
505a9a6cbd
commit
aba7df3afa
8 changed files with 90 additions and 2 deletions
|
@ -62,6 +62,7 @@ class ServerTransformer extends BaseClientTransformer
|
||||||
'cpu' => $server->cpu,
|
'cpu' => $server->cpu,
|
||||||
],
|
],
|
||||||
'invocation' => $service->handle($server, ! $this->getUser()->can(Permission::ACTION_STARTUP_READ, $server)),
|
'invocation' => $service->handle($server, ! $this->getUser()->can(Permission::ACTION_STARTUP_READ, $server)),
|
||||||
|
'egg_features' => $server->egg->inherit_features,
|
||||||
'feature_limits' => [
|
'feature_limits' => [
|
||||||
'databases' => $server->database_limit,
|
'databases' => $server->database_limit,
|
||||||
'allocations' => $server->allocation_limit,
|
'allocations' => $server->allocation_limit,
|
||||||
|
|
16
config/egg_features/eula.php
Normal file
16
config/egg_features/eula.php
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Egg Feature: EULA Popup
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This popup is enabled for Minecraft eggs and allows a custom frontend
|
||||||
|
| hook to run that monitors the console output of the server and pops up
|
||||||
|
| a modal asking the user to accept it if necessary.
|
||||||
|
|
|
||||||
|
| There is no additional configuration necessary.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
];
|
|
@ -30,6 +30,7 @@ export interface Server {
|
||||||
cpu: number;
|
cpu: number;
|
||||||
threads: string;
|
threads: string;
|
||||||
};
|
};
|
||||||
|
eggFeatures: string[];
|
||||||
featureLimits: {
|
featureLimits: {
|
||||||
databases: number;
|
databases: number;
|
||||||
allocations: number;
|
allocations: number;
|
||||||
|
@ -53,6 +54,7 @@ export const rawDataToServerObject = ({ attributes: data }: FractalResponseData)
|
||||||
},
|
},
|
||||||
description: data.description ? ((data.description.length > 0) ? data.description : null) : null,
|
description: data.description ? ((data.description.length > 0) ? data.description : null) : null,
|
||||||
limits: { ...data.limits },
|
limits: { ...data.limits },
|
||||||
|
eggFeatures: data.egg_features || [],
|
||||||
featureLimits: { ...data.feature_limits },
|
featureLimits: { ...data.feature_limits },
|
||||||
isSuspended: data.is_suspended,
|
isSuspended: data.is_suspended,
|
||||||
isInstalling: data.is_installing,
|
isInstalling: data.is_installing,
|
||||||
|
|
|
@ -8,6 +8,7 @@ import ServerContentBlock from '@/components/elements/ServerContentBlock';
|
||||||
import ServerDetailsBlock from '@/components/server/ServerDetailsBlock';
|
import ServerDetailsBlock from '@/components/server/ServerDetailsBlock';
|
||||||
import isEqual from 'react-fast-compare';
|
import isEqual from 'react-fast-compare';
|
||||||
import PowerControls from '@/components/server/PowerControls';
|
import PowerControls from '@/components/server/PowerControls';
|
||||||
|
import { EulaModalFeature } from '@feature/index';
|
||||||
|
|
||||||
export type PowerAction = 'start' | 'stop' | 'restart' | 'kill';
|
export type PowerAction = 'start' | 'stop' | 'restart' | 'kill';
|
||||||
|
|
||||||
|
@ -16,6 +17,8 @@ const ChunkedStatGraphs = lazy(() => import(/* webpackChunkName: "graphs" */'@/c
|
||||||
|
|
||||||
const ServerConsole = () => {
|
const ServerConsole = () => {
|
||||||
const isInstalling = ServerContext.useStoreState(state => state.server.data!.isInstalling);
|
const isInstalling = ServerContext.useStoreState(state => state.server.data!.isInstalling);
|
||||||
|
// @ts-ignore
|
||||||
|
const eggFeatures: string[] = ServerContext.useStoreState(state => state.server.data!.eggFeatures, isEqual);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ServerContentBlock title={'Console'} css={tw`flex flex-wrap`}>
|
<ServerContentBlock title={'Console'} css={tw`flex flex-wrap`}>
|
||||||
|
@ -41,6 +44,11 @@ const ServerConsole = () => {
|
||||||
<ChunkedConsole/>
|
<ChunkedConsole/>
|
||||||
<ChunkedStatGraphs/>
|
<ChunkedStatGraphs/>
|
||||||
</SuspenseSpinner>
|
</SuspenseSpinner>
|
||||||
|
{eggFeatures.includes('eula') &&
|
||||||
|
<React.Suspense fallback={null}>
|
||||||
|
<EulaModalFeature/>
|
||||||
|
</React.Suspense>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</ServerContentBlock>
|
</ServerContentBlock>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { ServerContext } from '@/state/server';
|
||||||
|
import Modal from '@/components/elements/Modal';
|
||||||
|
import tw from 'twin.macro';
|
||||||
|
|
||||||
|
const EulaModalFeature = () => {
|
||||||
|
const [ visible, setVisible ] = useState(false);
|
||||||
|
const status = ServerContext.useStoreState(state => state.status.value);
|
||||||
|
const { connected, instance } = ServerContext.useStoreState(state => state.socket);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!connected || !instance || status === 'running') return;
|
||||||
|
|
||||||
|
const listener = (line: string) => {
|
||||||
|
if (line.toLowerCase().indexOf('you need to agree to the eula in order to run the server') >= 0) {
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
instance.addListener('console output', listener);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
instance.removeListener('console output', listener);
|
||||||
|
};
|
||||||
|
}, [ connected, instance, status ]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
!visible ?
|
||||||
|
null
|
||||||
|
:
|
||||||
|
<Modal visible onDismissed={() => setVisible(false)}>
|
||||||
|
<h2 css={tw`text-3xl mb-4 text-neutral-100`}>EULA Not Accepted</h2>
|
||||||
|
<p css={tw`text-neutral-200`}>
|
||||||
|
It looks like you have not yet accepted the Minecraft EULA. In order to start this server you
|
||||||
|
must set eula=true inside the eula.txt file in the File Manager.
|
||||||
|
</p>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EulaModalFeature;
|
11
resources/scripts/components/server/features/index.ts
Normal file
11
resources/scripts/components/server/features/index.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { lazy } from 'react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom features should be registered here as lazy components so that they do
|
||||||
|
* not impact the generated JS bundle size. They will be automatically loaded in
|
||||||
|
* whenever they are actually loaded for the client (which may be never, depending
|
||||||
|
* on the feature and the egg).
|
||||||
|
*/
|
||||||
|
const EulaModalFeature = lazy(() => import(/* webpackChunkName: "feature.eula" */'@feature/eula/EulaModalFeature'));
|
||||||
|
|
||||||
|
export { EulaModalFeature };
|
|
@ -11,11 +11,17 @@
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"lib": ["es2015", "dom"],
|
"lib": [
|
||||||
|
"es2015",
|
||||||
|
"dom"
|
||||||
|
],
|
||||||
"importsNotUsedAsValues": "preserve",
|
"importsNotUsedAsValues": "preserve",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": [
|
"@/*": [
|
||||||
"./resources/scripts/*"
|
"./resources/scripts/*"
|
||||||
|
],
|
||||||
|
"@feature/*": [
|
||||||
|
"./resources/scripts/components/server/features/*"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
|
@ -23,7 +29,9 @@
|
||||||
"name": "typescript-plugin-tw-template"
|
"name": "typescript-plugin-tw-template"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"typeRoots": ["node_modules/@types"]
|
"typeRoots": [
|
||||||
|
"node_modules/@types"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"./resources/scripts/**/*"
|
"./resources/scripts/**/*"
|
||||||
|
|
|
@ -63,6 +63,7 @@ module.exports = {
|
||||||
extensions: ['.ts', '.tsx', '.js', '.json'],
|
extensions: ['.ts', '.tsx', '.js', '.json'],
|
||||||
alias: {
|
alias: {
|
||||||
'@': path.join(__dirname, '/resources/scripts'),
|
'@': path.join(__dirname, '/resources/scripts'),
|
||||||
|
'@feature': path.join(__dirname, '/resources/scripts/components/server/features'),
|
||||||
},
|
},
|
||||||
symlinks: false,
|
symlinks: false,
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue