Skip to content

Commit

Permalink
Added winter theme and basic linux support
Browse files Browse the repository at this point in the history
  • Loading branch information
Ipmake committed Dec 23, 2023
1 parent 1a156f3 commit 7feac5a
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 32 deletions.
2 changes: 1 addition & 1 deletion electron-builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ linux:
target:
- AppImage
# - snap
# - deb
- deb
maintainer: kocity.xyz
category: Game
appImage:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "knockoutcitylauncher",
"version": "2.0.0",
"version": "2.0.1",
"description": "Unofficial Knockout City Launcher",
"main": "./out/main/index.js",
"author": "IPGsystems",
Expand Down
56 changes: 34 additions & 22 deletions src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,35 +161,49 @@ function createWindow(): void {
win.focus()
})

ipcMain.on('clean-gamedir-mods', async (event, args: { basePath: string; gameVersion: number; }) => {
event.returnValue = undefined
ipcMain.on(
'clean-gamedir-mods',
async (event, args: { basePath: string; gameVersion: number }) => {
event.returnValue = undefined

const gameDirPath = path.join(
args.basePath,
args.gameVersion == 1 ? 'highRes' : 'lowRes',
'KnockoutCity'
)

const gameDirPath = path.join(args.basePath, args.gameVersion == 1 ? 'highRes' : 'lowRes', 'KnockoutCity')

const outDirPath = path.join(gameDirPath, 'out')
fs.rmSync(outDirPath, {recursive: true, force: true})
const outDirPath = path.join(gameDirPath, 'out')
fs.rmSync(outDirPath, { recursive: true, force: true })

const viperRootPath = path.join(gameDirPath, '.viper_root')
fs.rmSync(viperRootPath, {recursive: true, force: true})
const viperRootPath = path.join(gameDirPath, '.viper_root')
fs.rmSync(viperRootPath, { recursive: true, force: true })

const versionsPath = path.join(gameDirPath, 'version.json')
fs.rmSync(versionsPath, {recursive: true, force: true})
const versionsPath = path.join(gameDirPath, 'version.json')
fs.rmSync(versionsPath, { recursive: true, force: true })

event.sender.send('cleaned-gamedir-mods')
}
)

event.sender.send('cleaned-gamedir-mods')
})

ipcMain.on(
'install-server-mods',
async (event, args: { basePath: string; gameVersion: number; server: { name: string, addr: string } }) => {
async (
event,
args: { basePath: string; gameVersion: number; server: { name: string; addr: string } }
) => {
event.returnValue = undefined

const serverModsDownloadPath = path.join(args.basePath, 'downloads', 'mods', args.server.name)
const serverModsVersionPath = path.join(serverModsDownloadPath, 'version.json')
const gameDirPath = path.join(args.basePath, args.gameVersion == 1 ? 'highRes' : 'lowRes', 'KnockoutCity')
const gameDirPath = path.join(
args.basePath,
args.gameVersion == 1 ? 'highRes' : 'lowRes',
'KnockoutCity'
)

const result = (await axios.get(`http://${args.server.addr}/mods/list`)).data

const downloadMods = async () => {
const downloadMods = async (): Promise<void> => {
if (result.length === 0) {
return
}
Expand Down Expand Up @@ -478,7 +492,7 @@ function createWindow(): void {
? `mkdir "${arg.path}" && icacls "${arg.path}" /grant "${
os.userInfo().username
}":(OI)(CI)F /T`
: `mkdir "${arg.path}" && chown -R ${os.userInfo().username} "${arg.path}"`,
: `mkdir -p "${arg.path}" && chown -R ${os.userInfo().username} "${arg.path}"`,
{ name: 'Knockout City Launcher' },
(error) => {
if (error) reject(new Error(error.message)), console.log(error)
Expand Down Expand Up @@ -891,11 +905,9 @@ function createWindow(): void {
contextIsolation: false
}
})
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
cmd.loadURL(process.env['ELECTRON_RENDERER_URL'] + '/shell.html')
} else {
cmd.loadFile(path.join(__dirname, '../renderer/shell.html'))
}
if (is.dev && process.env['ELECTRON_RENDERER_URL'])
cmd.loadFile(path.join(process.env['ELECTRON_RENDERER_URL'], '../../resources/shell.html'))
else cmd.loadFile(path.join(__dirname, '../../resources/shell.html'))
}

server.stdout.on('data', (data) => {
Expand Down
1 change: 1 addition & 0 deletions src/preload/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ declare global {

interface Window {
version: string
isLinux: boolean
electron: typeof electron
getCurrentWindow: () => Electron.BrowserWindow
openMenu: (x: number, y: number) => void
Expand Down
17 changes: 13 additions & 4 deletions src/preload/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { ipcRenderer } from 'electron'
import { getCurrentWindow } from '@electron/remote'
import { BrowserWindow } from 'electron'
const os = require('os')

// Use `contextBridge` APIs to expose Electron APIs to
// renderer only if context isolation is enabled, otherwise
// just add to the DOM global.

// @ts-ignore (define in dts)
window.isLinux = os.platform() === 'linux'

if (!localStorage.getItem('username')) {
// get username from system
const username = require('os').userInfo().username
const username = os.userInfo().username
localStorage.setItem('username', username)
}
if (!localStorage.getItem('gameVersion')) localStorage.setItem('gameVersion', '1')
Expand All @@ -17,6 +21,11 @@ if (!localStorage.getItem('currServerName')) localStorage.setItem('currServerNam
if (!localStorage.getItem('currServer')) localStorage.setItem('currServer', '127.0.0.1')
if (localStorage.getItem('servers') === null)
localStorage.setItem('servers', '[{"name":"localhost","ip":"127.0.0.1"}]')
if (!localStorage.getItem('gameDirectory'))
localStorage.setItem(
'gameDirectory',
os.Platform() === 'win32' ? 'C:/Program Files/KOCity' : `${os.homedir()}/Games/KOCity`
)

if (localStorage.getItem('discordRPC:enabled') === null)
localStorage.setItem('discordRPC:enabled', 'true')
Expand Down Expand Up @@ -111,7 +120,7 @@ window.addEventListener('DOMContentLoaded', () => {
basePath: localStorage.getItem('gameDirectory'),
gameVersion: localStorage.getItem('gameVersion')
})
})
})
}

// @ts-ignore (define in dts)
Expand All @@ -124,10 +133,10 @@ window.addEventListener('DOMContentLoaded', () => {
gameVersion: localStorage.getItem('gameVersion'),
server: {
name: localStorage.getItem('currServerName'),
addr: localStorage.getItem('currServer'),
addr: localStorage.getItem('currServer')
}
})
})
})
}

// @ts-ignore (define in dts)
Expand Down
8 changes: 8 additions & 0 deletions src/renderer/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,12 @@ html, body {
.buttonCell {
width: 40px !important;
max-width: 40px !important;
}

.snowflake {
position: absolute;
aspect-ratio: 1/1;

background: white;
border-radius: 50%;
}
2 changes: 1 addition & 1 deletion src/renderer/src/components/ServersMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function ServersMenu(): JSX.Element {
>
<Tab label="Public" />
<Tab label="Private" />
<Tab label="Host" />
<Tab label="Host" disabled={window.isLinux} />
</Tabs>
<Box
style={{
Expand Down
59 changes: 59 additions & 0 deletions src/renderer/src/components/SnowFall.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Box } from '@mui/material'
import { useEffect } from 'react'

function SnowFall(): JSX.Element {
const snowflakeCount = 100
const snowflakeSize = 5
const snowflakeSpeed = 2

useEffect(() => {
const parent = document.getElementById('snowfall')
for (let i = 0; i < snowflakeCount; i++) {
const x = Math.random() * window.innerWidth
const y = Math.random() * window.innerHeight
const size = Math.random() * snowflakeSize
const speed = Math.random() * snowflakeSpeed

const snowflake = document.createElement('div')
snowflake.classList.add('snowflake')
snowflake.id = `snowflake-${i}`
snowflake.style.width = `${size}px`

snowflake.style.left = `${x}px`
snowflake.style.top = `${y}px`
snowflake.style.animationDuration = `${speed}s`

parent?.appendChild(snowflake)
}
const interval = setInterval(() => {
const snowflakes = document.querySelectorAll('.snowflake')
snowflakes.forEach((snowflake: Element, index) => {
// update snowflake position
const top = parseFloat((snowflake as HTMLElement).style.top)
const speed = parseFloat((snowflake as HTMLElement).style.animationDuration)
;(snowflake as HTMLElement).style.top = `${top + speed}px`
// reset snowflake position if it goes off screen
if (snowflake.getBoundingClientRect().top > window.innerHeight)
document.getElementById(`snowflake-${index}`)?.style.setProperty('top', '0px')
})
}, 1000 / 60)
return () => clearInterval(interval)
}, [])

return (
<Box
id="snowfall"
sx={{
position: 'absolute',
top: 0,
left: 0,
width: '100vw',
height: '100vh',
zIndex: 2000,
pointerEvents: 'none'
}}
/>
)
}

export default SnowFall
5 changes: 2 additions & 3 deletions src/renderer/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import ReactDOM from 'react-dom/client'
import './index.css'
import App from './App'
import { CssBaseline, ThemeProvider, createTheme } from '@mui/material'
import SnowFall from './components/SnowFall'

const darkTheme = createTheme({
palette: {
Expand All @@ -15,13 +16,11 @@ const darkTheme = createTheme({
}
})

if (!localStorage.getItem('gameDirectory'))
localStorage.setItem('gameDirectory', 'C:/Program Files/KOCity')

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
root.render(
<ThemeProvider theme={darkTheme}>
<CssBaseline />
<SnowFall />
<App />
</ThemeProvider>
)

0 comments on commit 7feac5a

Please sign in to comment.