-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit eec08dd
Showing
28 changed files
with
1,252 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
web | ||
node_modules |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
Blocks © 2024 by Nullvariable is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/4.0/ | ||
|
||
# Installing | ||
* Download the latest release. | ||
* Add to your NPWD: | ||
``` | ||
"apps": [ | ||
... | ||
"npwd_app_blocks" | ||
], | ||
``` | ||
* Add to your server.cfg and ensure it starts before NPWD | ||
|
||
# Building | ||
I use bun, but npm pnpm or whatever the latest hotness is should work too | ||
``` | ||
cd src | ||
bun install | ||
bun run build | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
fx_version 'cerulean' | ||
game "gta5" | ||
|
||
ui_page "web/dist/index.html" | ||
|
||
files { | ||
"web/dist/index.html", | ||
"web/dist/**/*", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
yarn-error.log | ||
node_modules | ||
dist | ||
web | ||
release |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
build | ||
node_modules | ||
*.json | ||
*.lock | ||
dist | ||
coverage | ||
*.md | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"printWidth": 100, | ||
"useTabs": false, | ||
"semi": true, | ||
"bracketSpacing": true, | ||
"jsxSingleQuote": false, | ||
"singleQuote": true, | ||
"tabWidth": 2, | ||
"trailingComma": "all" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
import React, { useState, useEffect } from 'react'; | ||
|
||
import { i18n } from 'i18next'; | ||
import { | ||
Theme, | ||
Paper, | ||
StyledEngineProvider, | ||
Button as MuiButton, | ||
} from '@mui/material'; | ||
import Header, { HEADER_HEIGHT } from './components/Header'; | ||
import styled from '@emotion/styled'; | ||
import ThemeSwitchProvider from './ThemeSwitchProvider'; | ||
import { RecoilRoot } from 'recoil'; | ||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; | ||
import { faCubesStacked } from '@fortawesome/free-solid-svg-icons'; | ||
import Game from './components/Game'; | ||
|
||
const Container = styled(Paper)` | ||
flex: 1; | ||
display: flex; | ||
flex-direction: column; | ||
box-sizing: border-box; | ||
max-height: 100%; | ||
`; | ||
|
||
const Content = styled.div` | ||
flex: 1; | ||
display: flex; | ||
flex-direction: column; | ||
box-sizing: border-box; | ||
padding: 1.5rem; | ||
max-height: calc(100% - ${HEADER_HEIGHT}); | ||
overflow: auto; | ||
background-color: #000; | ||
position: relative; | ||
`; | ||
|
||
const Score = styled.div` | ||
color: white; | ||
font-family: 'Press Start 2P', cursive; | ||
font-size: 24px; | ||
text-shadow: 2px 2px 0 #ff0000, 4px 4px 0 #ff9900; | ||
background: black; | ||
padding: 10px; | ||
border: 2px solid #00ff00; | ||
border-radius: 5px; | ||
display: inline-block; | ||
margin-bottom: 1rem; | ||
left: 50%; | ||
transform: translateX(-50%); | ||
position: relative; | ||
text-align: center; | ||
`; | ||
|
||
const Button = styled(MuiButton)` | ||
color: black; | ||
background-color: white; | ||
font-family: 'Press Start 2P', cursive; | ||
font-size: 24px; | ||
text-shadow: 2px 2px 0 #ff0000, 4px 4px 0 #ff9900; | ||
padding: 10px; | ||
border: 2px solid #00ff00; | ||
border-radius: 5px; | ||
display: inline-block; | ||
position: absolute; | ||
bottom: 1.5rem; | ||
left: 50%; | ||
transform: translateX(-50%); | ||
`; | ||
|
||
interface AppProps { | ||
theme: Theme; | ||
i18n: i18n; | ||
settings: any; | ||
} | ||
|
||
export function App(props: AppProps) { | ||
const [gameStarted, setGameStarted] = useState(false); | ||
const [gameOver, setGameOver] = useState(false); | ||
const [finalScore, setFinalScore] = useState(0); | ||
const [personalBest, setPersonalBest] = useState(0); | ||
const [lastScore, setLastScore] = useState(0); | ||
|
||
const handleGameOver = (score: React.SetStateAction<number>) => { | ||
setGameOver(true); | ||
setFinalScore(score); | ||
}; | ||
|
||
const startNewGame = () => { | ||
setGameStarted(true); | ||
setGameOver(false); | ||
setFinalScore(0); | ||
}; | ||
|
||
useEffect(() => { | ||
const storedPersonalBest = localStorage.getItem('personalBest'); | ||
const storedLastScore = localStorage.getItem('lastScore'); | ||
if (storedPersonalBest) setPersonalBest(Number(storedPersonalBest)); | ||
if (storedLastScore) setLastScore(Number(storedLastScore)); | ||
}, []); | ||
|
||
useEffect(() => { | ||
if (gameOver) { | ||
localStorage.setItem('lastScore', finalScore.toString()); | ||
setLastScore(finalScore); | ||
if (finalScore > personalBest) { | ||
localStorage.setItem('personalBest', finalScore.toString()); | ||
setPersonalBest(finalScore); | ||
} | ||
} | ||
}, [gameOver, finalScore, personalBest]); | ||
|
||
return ( | ||
<StyledEngineProvider injectFirst> | ||
<ThemeSwitchProvider mode={props.theme.palette.mode}> | ||
<Container square elevation={0}> | ||
<Header> | ||
<FontAwesomeIcon icon={faCubesStacked} /> Blocks | ||
</Header> | ||
<Content> | ||
{gameStarted ? ( | ||
gameOver ? (<> | ||
<Score>Final: {finalScore}</Score> | ||
<Score>Personal Best: {personalBest}</Score> | ||
<Score>Last Score: {lastScore}</Score> | ||
<Button variant="contained" onClick={startNewGame}> | ||
New Game | ||
</Button> | ||
</>) : ( | ||
<Game onGameOver={handleGameOver} /> | ||
) | ||
) : (<> | ||
<Score>Final: {finalScore}</Score> | ||
<Score>Personal Best: {personalBest}</Score> | ||
<Button variant="contained" onClick={startNewGame}> | ||
New Game | ||
</Button> | ||
</>)} | ||
</Content> | ||
</Container> | ||
</ThemeSwitchProvider> | ||
</StyledEngineProvider> | ||
); | ||
} | ||
|
||
export default function WithProviders(props: AppProps) { | ||
return ( | ||
<RecoilRoot override key="broker"> | ||
<App {...props} /> | ||
</RecoilRoot> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { createTheme, ThemeProvider } from '@mui/material'; | ||
import React from 'react'; | ||
import { ReactNode } from 'react'; | ||
import { themes } from './app.theme'; | ||
|
||
interface ThemeSwitchProviderProps { | ||
mode: 'light' | 'dark'; | ||
children: ReactNode; | ||
} | ||
const ThemeSwitchProvider = ({ children, mode }: ThemeSwitchProviderProps) => { | ||
const themeOptions = themes[mode]; | ||
const theme = createTheme(themeOptions); | ||
|
||
return <ThemeProvider theme={theme}>{children}</ThemeProvider>; | ||
}; | ||
|
||
export default ThemeSwitchProvider; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { common, green } from '@mui/material/colors'; | ||
import { ThemeOptions } from '@mui/material'; | ||
|
||
export const APP_PRIMARY_COLOR = "#83BBCE"; | ||
|
||
export const LIGHT_APP_TEXT_COLOR = common.white; | ||
export const DARK_APP_TEXT_COLOR = common.white; | ||
|
||
export const lightTheme: ThemeOptions = { | ||
palette: { | ||
mode: 'light', | ||
primary: { | ||
main: APP_PRIMARY_COLOR, | ||
dark: "#176971", | ||
light: "#176971", | ||
contrastText: LIGHT_APP_TEXT_COLOR, | ||
}, | ||
secondary: { | ||
main: '#d32f2f', | ||
light: '#eb4242', | ||
dark: '#941212', | ||
contrastText: LIGHT_APP_TEXT_COLOR, | ||
}, | ||
success: { | ||
main: '#2196f3', | ||
contrastText: LIGHT_APP_TEXT_COLOR, | ||
}, | ||
}, | ||
}; | ||
|
||
export const darkTheme: ThemeOptions = { | ||
palette: { | ||
mode: 'dark', | ||
primary: { | ||
main: APP_PRIMARY_COLOR, | ||
dark: "#176971", | ||
light: "#fff", | ||
contrastText: LIGHT_APP_TEXT_COLOR, | ||
}, | ||
secondary: { | ||
main: '#d32f2f', | ||
light: '#eb4242', | ||
dark: '#941212', | ||
contrastText: LIGHT_APP_TEXT_COLOR, | ||
}, | ||
success: { | ||
main: '#2196f3', | ||
contrastText: LIGHT_APP_TEXT_COLOR, | ||
}, | ||
}, | ||
}; | ||
|
||
export const themes: Record<'dark' | 'light', ThemeOptions> = { | ||
light: lightTheme, | ||
dark: darkTheme, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { atom, useRecoilState } from "recoil"; | ||
|
||
const themeMode = atom({ | ||
key: 'appThemeMode', | ||
default: false, | ||
}) | ||
|
||
export const useThemeMode = () => useRecoilState(themeMode); |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
import('./index'); |
Binary file not shown.
Oops, something went wrong.