Skip to content

Commit decd7f4

Browse files
committed
Refactor server list queries to support offline servers
- Update server list pages to query GameServer instead of GameServerState - Modify server list rendering to handle both online and offline servers - Add support for displaying offline server information in server lists - Implement separate row components for online and offline servers - Update List component to handle undefined labels
1 parent 4f4e0ff commit decd7f4

File tree

7 files changed

+279
-138
lines changed

7 files changed

+279
-138
lines changed

apps/frontend/app/all/servers/page.tsx

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,37 +16,64 @@ export default async function Index({
1616
}) {
1717
const { page } = searchParamSchema.parse(searchParams);
1818

19-
const gameServerStates = await prisma.gameServerState.findMany({
20-
orderBy: {
21-
numClients: 'desc',
22-
},
23-
include: {
24-
gameServer: true,
25-
map: true,
19+
const gameServers = await prisma.gameServer.findMany({
20+
select: {
21+
ip: true,
22+
port: true,
23+
gameServerState: {
24+
select: {
25+
name: true,
26+
numClients: true,
27+
maxClients: true,
28+
map: {
29+
select: {
30+
gameTypeName: true,
31+
name: true,
32+
},
33+
},
34+
},
35+
},
2636
},
37+
orderBy: [
38+
{
39+
failureCount: 'asc',
40+
},
41+
{
42+
gameServerState: {
43+
maxClients: 'desc',
44+
},
45+
},
46+
{
47+
gameServerState: {
48+
numClients: 'desc',
49+
},
50+
},
51+
{
52+
playTime: 'desc',
53+
},
54+
],
2755
take: 100,
2856
skip: (page - 1) * 100,
2957
});
3058

3159
const globalCounts = await getGlobalCounts(redis);
3260

33-
const servers = gameServerStates
34-
.map((gameServerState, index) => (gameServerState.gameServer ? {
35-
rank: (page - 1) * 100 + index + 1,
36-
name: gameServerState.name,
37-
gameTypeName: gameServerState.map.gameTypeName,
38-
mapName: gameServerState.map.name,
39-
numClients: gameServerState.numClients,
40-
maxClients: gameServerState.maxClients,
41-
ip: gameServerState.gameServer.ip,
42-
port: gameServerState.gameServer.port,
43-
} : null))
44-
.filter((server) => server !== null);
61+
const servers = gameServers.map((gameServer, index) => ({
62+
rank: (page - 1) * 100 + index + 1,
63+
ip: gameServer.ip,
64+
port: gameServer.port,
65+
state: gameServer.gameServerState
66+
? {
67+
name: gameServer.gameServerState.name,
68+
gameTypeName: gameServer.gameServerState.map.gameTypeName,
69+
mapName: gameServer.gameServerState.map.name,
70+
numClients: gameServer.gameServerState.numClients,
71+
maxClients: gameServer.gameServerState.maxClients,
72+
}
73+
: null,
74+
}));
4575

4676
return (
47-
<ServerList
48-
serverCount={globalCounts.gameServers}
49-
servers={servers}
50-
/>
77+
<ServerList serverCount={globalCounts.gameServers} servers={servers} />
5178
);
5279
}

apps/frontend/app/gametype/[gameTypeName]/(lists)/servers/page.tsx

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,48 +17,56 @@ export default async function Index({
1717
const { page } = searchParamsSchema.parse(searchParams);
1818
const { gameTypeName } = paramsSchema.parse(params);
1919

20-
const gameServerStates = await prisma.gameServerState.findMany({
20+
const gameServers = await prisma.gameServer.findMany({
2121
select: {
22-
name: true,
23-
numClients: true,
24-
maxClients: true,
25-
map: {
22+
ip: true,
23+
port: true,
24+
gameServerState: {
2625
select: {
2726
name: true,
28-
gameTypeName: true,
29-
},
30-
},
31-
gameServer: {
32-
select: {
33-
ip: true,
34-
port: true,
27+
numClients: true,
28+
maxClients: true,
29+
map: {
30+
select: {
31+
name: true,
32+
gameTypeName: true,
33+
},
34+
},
3535
},
3636
},
3737
},
3838
where: {
39-
map: {
40-
gameTypeName: {
41-
equals: gameTypeName,
39+
gameServerState: {
40+
map: {
41+
gameTypeName: {
42+
equals: gameTypeName,
43+
},
4244
},
4345
},
4446
},
4547
orderBy: [
4648
{
47-
numClients: 'desc',
49+
gameServerState: {
50+
numClients: 'desc',
51+
},
4852
},
4953
{
50-
maxClients: 'desc',
54+
gameServerState: {
55+
maxClients: 'desc',
56+
},
5157
},
5258
],
5359
take: 100,
5460
skip: (page - 1) * 100,
5561
});
5662

57-
const serverCount = await prisma.gameServerState.count({
63+
const serverCount = await prisma.gameServer.count({
5864
where: {
59-
map: {
60-
gameTypeName: {
61-
equals: gameTypeName,
65+
gameServerState: {
66+
map: {
67+
gameTypeName: {
68+
equals: gameTypeName,
69+
},
6270
},
6371
},
6472
},
@@ -67,15 +75,19 @@ export default async function Index({
6775
return (
6876
<ServerList
6977
serverCount={serverCount}
70-
servers={gameServerStates.map((gameServerState, index) => ({
78+
servers={gameServers.map((gameServer, index) => ({
7179
rank: (page - 1) * 100 + index + 1,
72-
name: gameServerState.name,
73-
gameTypeName: gameServerState.map.gameTypeName,
74-
mapName: gameServerState.map.name ?? '',
75-
numClients: gameServerState.numClients,
76-
maxClients: gameServerState.maxClients,
77-
ip: gameServerState.gameServer?.ip ?? '',
78-
port: gameServerState.gameServer?.port ?? 0,
80+
ip: gameServer.ip,
81+
port: gameServer.port,
82+
state: gameServer.gameServerState
83+
? {
84+
name: gameServer.gameServerState.name,
85+
gameTypeName: gameServer.gameServerState.map.gameTypeName,
86+
mapName: gameServer.gameServerState.map.name,
87+
numClients: gameServer.gameServerState.numClients,
88+
maxClients: gameServer.gameServerState.maxClients,
89+
}
90+
: null,
7991
}))}
8092
/>
8193
);

apps/frontend/app/gametype/[gameTypeName]/map/[mapName]/servers/page.tsx

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,54 +17,62 @@ export default async function Index({
1717
const { page } = searchParamsSchema.parse(searchParams);
1818
const { gameTypeName, mapName } = paramsSchema.parse(params);
1919

20-
const gameServerStates = await prisma.gameServerState.findMany({
20+
const gameServers = await prisma.gameServer.findMany({
2121
select: {
22-
name: true,
23-
numClients: true,
24-
maxClients: true,
25-
map: {
22+
ip: true,
23+
port: true,
24+
gameServerState: {
2625
select: {
2726
name: true,
28-
gameTypeName: true,
29-
},
30-
},
31-
gameServer: {
32-
select: {
33-
ip: true,
34-
port: true,
27+
numClients: true,
28+
maxClients: true,
29+
map: {
30+
select: {
31+
name: true,
32+
gameTypeName: true,
33+
},
34+
},
3535
},
3636
},
3737
},
3838
where: {
39-
map: {
40-
name: {
41-
equals: mapName,
42-
},
43-
gameTypeName: {
44-
equals: gameTypeName,
39+
gameServerState: {
40+
map: {
41+
name: {
42+
equals: mapName,
43+
},
44+
gameTypeName: {
45+
equals: gameTypeName,
46+
},
4547
},
4648
},
4749
},
4850
orderBy: [
4951
{
50-
numClients: 'desc',
52+
gameServerState: {
53+
numClients: 'desc',
54+
},
5155
},
5256
{
53-
maxClients: 'desc',
57+
gameServerState: {
58+
maxClients: 'desc',
59+
},
5460
},
5561
],
5662
take: 100,
5763
skip: (page - 1) * 100,
5864
});
5965

60-
const serverCount = await prisma.gameServerState.count({
66+
const serverCount = await prisma.gameServer.count({
6167
where: {
62-
map: {
63-
name: {
64-
equals: mapName,
65-
},
66-
gameTypeName: {
67-
equals: gameTypeName,
68+
gameServerState: {
69+
map: {
70+
name: {
71+
equals: mapName,
72+
},
73+
gameTypeName: {
74+
equals: gameTypeName,
75+
},
6876
},
6977
},
7078
},
@@ -73,15 +81,19 @@ export default async function Index({
7381
return (
7482
<ServerList
7583
serverCount={serverCount}
76-
servers={gameServerStates.map((gameServerState, index) => ({
84+
servers={gameServers.map((gameServer, index) => ({
7785
rank: (page - 1) * 100 + index + 1,
78-
name: gameServerState.name,
79-
gameTypeName: gameServerState.map.gameTypeName,
80-
mapName: gameServerState.map.name ?? '',
81-
numClients: gameServerState.numClients,
82-
maxClients: gameServerState.maxClients,
83-
ip: gameServerState.gameServer?.ip ?? '',
84-
port: gameServerState.gameServer?.port ?? 0,
86+
ip: gameServer.ip,
87+
port: gameServer.port,
88+
state: gameServer.gameServerState
89+
? {
90+
name: gameServer.gameServerState.name,
91+
gameTypeName: gameServer.gameServerState.map.gameTypeName,
92+
mapName: gameServer.gameServerState.map.name,
93+
numClients: gameServer.gameServerState.numClients,
94+
maxClients: gameServer.gameServerState.maxClients,
95+
}
96+
: null,
8597
}))}
8698
/>
8799
);

apps/frontend/app/search/servers/page.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ export default async function Index({
3333
serverCount={gameServers.length}
3434
servers={gameServers.map((gameServer, index) => ({
3535
rank: index + 1,
36-
name: gameServer.name,
37-
gameTypeName: gameServer.gameTypeName,
38-
mapName: gameServer.mapName,
3936
ip: gameServer.ip,
4037
port: gameServer.port,
41-
numClients: gameServer.numClients,
42-
maxClients: gameServer.maxClients,
38+
state: {
39+
name: gameServer.name,
40+
gameTypeName: gameServer.gameTypeName,
41+
mapName: gameServer.mapName,
42+
numClients: gameServer.numClients,
43+
maxClients: gameServer.maxClients,
44+
},
4345
}))}
4446
/>
4547
</LayoutTabs>

apps/frontend/app/server/[ip]/[port]/page.tsx

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import { searchParamPageSchema } from '../../../../utils/page';
88
import prisma from '../../../../utils/prisma';
99
import { encodeString } from '../../../../utils/encoding';
1010
import { formatPlayTime } from '../../../../utils/format';
11+
import { GameServer } from '@prisma/client';
12+
import { formatDuration, intervalToDuration } from 'date-fns';
1113

1214
export const metadata = {
1315
title: 'Server',
@@ -23,6 +25,31 @@ function ipAndPort(ip: string, port: number) {
2325
}
2426
}
2527

28+
function OfflineServer({ gameServer }: { gameServer: GameServer }) {
29+
return (
30+
<main className="flex flex-col gap-8 py-12">
31+
<header className="flex flex-row px-20 gap-8">
32+
<section className="flex flex-col gap-2 grow">
33+
<h1 className="text-2xl font-bold">
34+
{ipAndPort(gameServer.ip, gameServer.port)}
35+
</h1>
36+
<div className="flex flex-row divide-x">
37+
<span className="pr-4">
38+
Offline for{' '}
39+
{formatDuration(
40+
intervalToDuration({
41+
start: gameServer.lastSeenAt,
42+
end: new Date(),
43+
})
44+
)}
45+
</span>
46+
</div>
47+
</section>
48+
</header>
49+
</main>
50+
);
51+
}
52+
2653
export default async function Index({
2754
params,
2855
searchParams,
@@ -67,15 +94,21 @@ export default async function Index({
6794
},
6895
});
6996

70-
if (gameServer === null || gameServer.gameServerState === null) {
97+
if (gameServer === null) {
7198
return notFound();
7299
}
73100

101+
if (gameServer.gameServerState === null) {
102+
return <OfflineServer gameServer={gameServer} />;
103+
}
104+
74105
return (
75106
<main className="flex flex-col gap-8 py-12">
76107
<header className="flex flex-row px-20 gap-8">
77108
<section className="flex flex-col gap-2 grow">
78-
<h1 className="text-2xl font-bold">{gameServer.gameServerState.name}</h1>
109+
<h1 className="text-2xl font-bold">
110+
{gameServer.gameServerState.name}
111+
</h1>
79112
<div className="flex flex-row divide-x">
80113
<span className="pr-4">
81114
<Link

0 commit comments

Comments
 (0)