Skip to content

Commit

Permalink
Merge pull request #4 from Kensaa/server-rework
Browse files Browse the repository at this point in the history
Server rework
  • Loading branch information
Kensaa committed Jan 13, 2024
2 parents 1cfda2d + 82b7e36 commit 26b7ffc
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 42 deletions.
2 changes: 0 additions & 2 deletions launcher/electron/electron.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,6 @@ ipcMain.handle('start-game', async (_, args: StartArgs) => {
})

launcher.on('progress', progress => {
console.log(progress)
const {
type,
task: current,
Expand All @@ -344,7 +343,6 @@ ipcMain.handle('start-game', async (_, args: StartArgs) => {
})

try {
console.log(args)
if (args.server === 'local') {
await launchGameLocal(args)
} else if (args.server !== '') {
Expand Down
2 changes: 1 addition & 1 deletion launcher/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "A Minecraft launcher with auto-update feature to facilitate playing modded minecraft",
"author": "Kensa",
"private": true,
"version": "3.0.0",
"version": "3.1.0",
"license": "MIT",
"main": "dist-electron/electron.js",
"scripts": {
Expand Down
32 changes: 24 additions & 8 deletions launcher/src/components/ProfilePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ export default function ProfilePicker() {
ipcRenderer.send('set-selected-profile', profile)
}

const currentServer = profiles[selectedProfile[0]] ?? []
const profile = currentServer[selectedProfile[1]] ?? undefined
console.log(selectedProfile)
const currentServer = profiles[selectedProfile[0]] ?? {
profiles: [],
address: ''
}
const profile = currentServer.profiles[selectedProfile[1]] ?? undefined

return (
<div
Expand All @@ -30,11 +34,11 @@ export default function ProfilePicker() {
>
<Dropdown className='w-100 h-100'>
<Dropdown.Toggle
disabled={!currentServer.length || fetching}
disabled={!currentServer.profiles.length || fetching}
style={{ width: '350px' }}
className='d-flex flex-column align-items-center'
variant={
!currentServer.length && !fetching
!currentServer.profiles.length && !fetching
? 'danger'
: 'transparent'
}
Expand All @@ -47,11 +51,14 @@ export default function ProfilePicker() {
</Dropdown.Toggle>
<Dropdown.Menu className='w-100'>
{Object.entries(profiles).map(
([server, profiles], serverIndex) => {
([server, { profiles, address }], serverIndex) => {
if (!profiles.length) return null
return (
<div key={serverIndex}>
<Divider text={server} />
<Divider
serverName={server}
address={address}
/>
{profiles.map((profile, profileIndex) => (
<Dropdown.Item
key={
Expand All @@ -77,10 +84,19 @@ export default function ProfilePicker() {
)
}

function Divider({ text }: { text: string }) {
interface DividerProps {
serverName: string
address: string
}

function Divider({ serverName, address }: DividerProps) {
return (
<div className='d-flex flex-row align-items-center justify-content-center user-select-none mt-3'>
<label style={{ color: 'white' }}>{text}</label>
<label style={{ color: 'white' }}>
{serverName === address
? serverName
: `${serverName} (${address})`}
</label>
</div>
)
}
6 changes: 4 additions & 2 deletions launcher/src/pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,12 @@ export default function Home({
}, [])

const startGame = () => {
const profile = profiles[selectedProfile[0]][selectedProfile[1]]
const profile =
profiles[selectedProfile[0]].profiles[selectedProfile[1]]
const address = profiles[selectedProfile[0]].address
const args: StartArgs = {
profile,
server: selectedProfile[0]
server: address
}

setOverlay(<TaskOverlay title='Starting Game' />)
Expand Down
65 changes: 52 additions & 13 deletions launcher/src/stores/profiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@ import { useConfig } from './config'
import { Profile } from '../types'
import { useEffect, useState } from 'react'

interface ServerProfiles {
address: string
profiles: Profile[]
}

interface profileStore {
remoteProfiles: Record<string, Profile[]>
remoteProfiles: Record<string, ServerProfiles>
localProfiles: Profile[]
fetching: boolean
fetchRemoteProfiles: () => void
setLocalProfiles: (profiles: Profile[]) => void

//[server name, profile index]
selectedProfile: [string, number]
setSelectedProfile: (profile: [string, number]) => void
}
Expand All @@ -25,23 +31,51 @@ const useStore = create<profileStore>(set => {

const fetchRemoteProfiles = () => {
const servers = useConfig.getState().servers
const profiles: Record<string, Profile[]> = {}
const profiles: Record<string, ServerProfiles> = {}
set({ fetching: true })

const seenServers = new Set<string>()

Promise.all(
servers.map(server =>
fetch(server + '/profiles')
.then(res => res.json())
.then(data => [server, data])
.then(res => {
//get the server name from the headers
const serverName = res.headers.get('X-Server-Name')
if (serverName) {
// if there is a server name, check if we already have seen it, if so, return nothing
if (seenServers.has(serverName)) return undefined
// if we haven't seen it, add it to the list of seen servers
seenServers.add(serverName)
}
//then return the profiles
// the name is either the server name or the server address
return res.json().then(serverProfiles => {
return {
name: serverName ?? server,
data: {
address: server,
profiles: serverProfiles as Profile[]
}
}
})
})
.catch(err => {
console.log(err)
console.log('unable to fetch profiles from ' + server)
return [server, []]
return {
name: server,
data: { address: server, profiles: [] as Profile[] }
}
})
)
).then(responses => {
console.log('resp', responses)
for (const response of responses) {
if (!response) continue
const [server, data] = response
profiles[server] = data

const { name, data } = response
profiles[name] = data
}
set({ remoteProfiles: profiles, fetching: false })
})
Expand Down Expand Up @@ -74,10 +108,13 @@ export const useProfiles = () => {
remoteProfiles: state.remoteProfiles
}))

const [profiles, setProfiles] = useState<Record<string, Profile[]>>({})
const [profiles, setProfiles] = useState<Record<string, ServerProfiles>>({})

useEffect(() => {
setProfiles({ ...remoteProfiles, local: localProfiles })
setProfiles({
...remoteProfiles,
local: { address: 'local', profiles: localProfiles }
})
}, [localProfiles, remoteProfiles])

return profiles
Expand All @@ -103,13 +140,15 @@ export const useSelectedProfile = () => {

useEffect(() => {
if (Object.keys(profiles).length === 0 || fetching) return

if (
!profiles[selectedProfile[0]] ||
selectedProfile[1] >=
Object.keys(profiles[selectedProfile[0]]).length
selectedProfile[1] >= profiles[selectedProfile[0]].profiles.length
) {
ipcRenderer.send('set-selected-profile', [0, 0])
setSelectedProfile([servers[0], 0])
const firstServer = Object.entries(profiles)[0]
const newSelectedProfile = [firstServer[0], 0] as [string, number]
ipcRenderer.send('set-selected-profile', newSelectedProfile)
setSelectedProfile(newSelectedProfile)
}
}, [profiles, servers])

Expand Down
1 change: 1 addition & 0 deletions server/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ ENV PROFILES_FILE="/data/profiles.json"
ENV STATIC_FOLDER="/data/static/"
ENV PORT="40069"
ENV ADDRESS=""
ENV SERVER_NAME=""
ENV CDNS=""

EXPOSE 40069
Expand Down
27 changes: 14 additions & 13 deletions server/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
version: "3.8"
version: '3.8'

services:
launcher-server:
image: kensa/kensa-minecraft-launcher-server
ports:
- "40069:40069/tcp"
environment:
PORT: 40069
ADDRESS: ''
staticFolder: '/data/static'
profilesFile: '/data/profiles.json'
CDNS: ''
volumes:
- /mnt/kensa-launcher/:/data
launcher-server:
image: kensa/kensa-minecraft-launcher-server
ports:
- '40069:40069/tcp'
environment:
PORT: 40069
ADDRESS: ''
staticFolder: '/data/static'
profilesFile: '/data/profiles.json'
SERVER_NAME: ''
CDNS: ''
volumes:
- /mnt/kensa-launcher/:/data
2 changes: 1 addition & 1 deletion server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kensa-minecraft-launcher-server",
"version": "0.0.5",
"version": "2.0.0",
"main": "dist/server.js",
"author": "Kensa",
"license": "MIT",
Expand Down
24 changes: 22 additions & 2 deletions server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import * as fs from 'fs'
import * as crypto from 'crypto'
import 'source-map-support/register'

const PORT = process.env.PORT || 40069
const PORT = parseInt(process.env.PORT || '40069')
const ADDRESS = process.env.ADDRESS
const staticFolder = process.env.STATIC_FOLDER || './static'
const profilesFile = process.env.PROFILES_FILE || './profiles.json'
const CDNS = process.env.CDNS || ''
const SERVER_NAME =
process.env.SERVER_NAME || crypto.randomBytes(4).toString('hex')

const version = JSON.parse(
fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf-8')
Expand All @@ -28,6 +30,12 @@ if (!ADDRESS) {
)
}

if (process.env.SERVER_NAME === undefined) {
console.log(
`SERVER_NAME environement variables is not defined, using a random name : ${SERVER_NAME}`
)
}

if (!staticFolder) {
console.log(`static folder not defined in environment variables`)
process.exit(1)
Expand Down Expand Up @@ -98,10 +106,22 @@ function syncCDNS() {
const app = express()
let hashTree = (await hashFolder(staticFolder)) as Record<string, any>

app.use(cors())
app.use(
cors({
exposedHeaders: '*'
})
)
app.use(express.json())
app.use('/static/', express.static(staticFolder))

app.use((req, res, next) => {
// Access-Control-Request-Headers

//res.setHeader('Access-Control-Request-Headers', '*')
res.setHeader('X-Server-Name', SERVER_NAME)
next()
})

app.get('/', (req, res) => {
res.sendStatus(200)
})
Expand Down

0 comments on commit 26b7ffc

Please sign in to comment.