-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbasic.html
218 lines (186 loc) · 13.3 KB
/
basic.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GamerGirls Valheim Server Status</title>
<link rel="icon"
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' x='0px' y='0px' width='64' height='64' viewBox='0 0 64 64'%3E%3CradialGradient id='OD9qOsFrAhRH5kH1_kXada_RVN4KwWDfOXG_gr1' cx='33.211' cy='1965.619' r='42.955' gradientTransform='translate(0 -1934)' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23afeeff'%3E%3C/stop%3E%3Cstop offset='.193' stop-color='%23bbf1ff'%3E%3C/stop%3E%3Cstop offset='.703' stop-color='%23d7f8ff'%3E%3C/stop%3E%3Cstop offset='1' stop-color='%23e1faff'%3E%3C/stop%3E%3C/radialGradient%3E%3Cpath fill='url(%23OD9qOsFrAhRH5kH1_kXada_RVN4KwWDfOXG_gr1)' d='M63.99,36.31C64.1,38.33,62.5,40,60.5,40h-9.48C51.009,40,51,40.009,51,40.02v5.96 c0,0.011,0.009,0.02,0.02,0.02h9.48c1.58,0,2.81,1.46,2.43,3.11C62.66,50.25,61.54,51,60.37,51H59.5c-0.825,0-1.5,0.675-1.5,1.5l0,0 c0,0.825,0.675,1.5,1.5,1.5l0,0c2,0,3.6,1.67,3.49,3.69C62.9,59.58,61.2,61,59.3,61H4c-2.48,0-4.43-2.26-3.92-4.82 C0.47,54.29,2.25,53,4.18,53H5c2.92,0,5.26-2.51,4.98-5.49C9.73,44.91,7.4,43,4.78,43H4c-2.48,0-4.43-2.26-3.92-4.82 C0.47,36.29,2.07,35,4,35l0,0c1.301,0,2.332-1.252,1.899-2.634C5.633,31.52,4.776,31,3.89,31H3.5c-2,0-3.6-1.67-3.49-3.69 C0.1,25.42,1.8,24,3.7,24h7.28c0.011,0,0.02-0.009,0.02-0.02v-4.96c0-0.011-0.009-0.02-0.02-0.02H3.5 c-1.577,0-2.805-1.445-2.432-3.091C1.329,14.757,2.448,14,3.63,14H4.5C5.33,14,6,13.33,6,12.5S5.33,11,4.5,11h-1 c-2,0-3.6-1.67-3.49-3.69C0.1,5.42,1.8,4,3.7,4H60c2.34,0,4.21,2.01,3.98,4.39c-0.19,2.05-2,3.56-4.04,3.61H58.5 c-2.485,0-4.5,2.015-4.5,4.5l0,0c0,2.485,0,4.5,0,4.5h6c2.48,0,4.43,2.26,3.92,4.82C63.53,27.71,61.93,29,60,29l0,0 c-1.1,0-2,0.9-2,2l0,0c0,1.1,0.9,2,2,2h0.3C62.2,33,63.9,34.42,63.99,36.31z'%3E%3C/path%3E%3ClinearGradient id='OD9qOsFrAhRH5kH1_kXadb_RVN4KwWDfOXG_gr2' x1='32' x2='32' y1='3.779' y2='81.539' gradientTransform='translate(0 2)' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.096' stop-color='%235e6d7b'%3E%3C/stop%3E%3Cstop offset='.505' stop-color='%235c6b79'%3E%3C/stop%3E%3Cstop offset='1' stop-color='%23515c69'%3E%3C/stop%3E%3C/linearGradient%3E%3Cpath fill='url(%23OD9qOsFrAhRH5kH1_kXadb_RVN4KwWDfOXG_gr2)' d='M18,8h28c5.523,0,10,4.477,10,10v28 c0,5.523-4.477,10-10,10H18c-5.523,0-10-4.477-10-10V18C8,12.477,12.477,8,18,8z'%3E%3C/path%3E%3ClinearGradient id='OD9qOsFrAhRH5kH1_kXadc_RVN4KwWDfOXG_gr3' x1='16.502' x2='16.502' y1='-2.541' y2='31.054' gradientTransform='translate(0 2)' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%236c7985'%3E%3C/stop%3E%3Cstop offset='.279' stop-color='%236c7985'%3E%3C/stop%3E%3Cstop offset='.359' stop-color='%23697884'%3E%3C/stop%3E%3Cstop offset='.728' stop-color='%2365727e'%3E%3C/stop%3E%3Cstop offset='1' stop-color='%235f6975'%3E%3C/stop%3E%3C/linearGradient%3E%3Cpath fill='url(%23OD9qOsFrAhRH5kH1_kXadc_RVN4KwWDfOXG_gr3)' d='M24.99,10.24c0.15,1.5-1.02,2.76-2.49,2.76 h-8c-0.83,0-1.5,0.67-1.5,1.5s0.67,1.5,1.5,1.5s1.5,0.67,1.5,1.5S15.33,19,14.5,19H8v-1c0-5.52,4.48-10,10-10h4.36 C23.67,8,24.86,8.94,24.99,10.24z'%3E%3C/path%3E%3ClinearGradient id='OD9qOsFrAhRH5kH1_kXadd_RVN4KwWDfOXG_gr4' x1='45.998' x2='45.998' y1='18.368' y2='61.47' gradientTransform='translate(0 2)' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='.085' stop-color='%235e6d7b'%3E%3C/stop%3E%3Cstop offset='.421' stop-color='%235c6b79'%3E%3C/stop%3E%3Cstop offset='1' stop-color='%23515c69'%3E%3C/stop%3E%3C/linearGradient%3E%3Cpath fill='url(%23OD9qOsFrAhRH5kH1_kXadd_RVN4KwWDfOXG_gr4)' d='M56,44v2c0,5.52-4.48,10-10,10h-7.36 c-1.3,0-2.5-0.94-2.63-2.24C35.86,52.26,37.03,51,38.5,51h10c0.83,0,1.5-0.67,1.5-1.5S49.33,48,48.5,48h-0.38 c-1,0-1.93-0.68-2.09-1.66C45.82,45.09,46.79,44,48,44H56z'%3E%3C/path%3E%3ClinearGradient id='OD9qOsFrAhRH5kH1_kXade_RVN4KwWDfOXG_gr5' x1='32.108' x2='32.108' y1='13.033' y2='55.001' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23f4a05e'%3E%3C/stop%3E%3Cstop offset='.413' stop-color='%23fe6459'%3E%3C/stop%3E%3Cstop offset='.83' stop-color='%23ffcd49'%3E%3C/stop%3E%3Cstop offset='1' stop-color='%23ffde44'%3E%3C/stop%3E%3C/linearGradient%3E%3Cpath fill='url(%23OD9qOsFrAhRH5kH1_kXade_RVN4KwWDfOXG_gr5)' d='M18.371,15.84 c-0.064-0.02-0.111-0.074-0.122-0.14c-0.011-0.066,0.016-0.133,0.07-0.172c0.282-0.206,0.512-0.398,0.674-0.54 c0.175-0.154,0.398-0.241,0.631-0.248l7.719-0.227c0.077-0.002,0.149,0.039,0.186,0.107s0.032,0.151-0.012,0.215l-1.23,1.758 c-0.181,0.258-0.235,0.584-0.148,0.887l6.028,20.977c0.011,0.039,0.047,0.066,0.087,0.066c0.04,0,0.076-0.026,0.088-0.064 l6.596-21.253c0.042-0.134,0.034-0.279-0.023-0.407c-0.149-0.341-0.473-1.031-0.812-1.435c-0.082-0.097-0.096-0.235-0.035-0.347 c0.166-0.304,0.599-0.578,0.811-0.699c0.076-0.044,0.162-0.065,0.25-0.061l6.703,0.231c0.062,0.002,0.115,0.043,0.133,0.102 c0.018,0.059-0.003,0.123-0.053,0.159l-2.196,1.597c-0.14,0.102-0.244,0.245-0.299,0.409C43.031,17.908,41.438,22.685,41,24 c-0.5,1.5-4.25,12.25-4.25,13c0,0.684-3.945,10.711-4.834,13.808c-0.03,0.105-0.123,0.18-0.232,0.187 c-0.109,0.007-0.211-0.055-0.254-0.155c-1.21-2.787-2.701-9.173-2.93-10.09c-0.25-1-1.25-6-2-7.25S22.25,20.25,21.75,19 C21.291,17.852,19.777,16.282,18.371,15.84z'%3E%3C/path%3E%3C/svg%3E">
</path>
<style>
body {
font-family: Arial, sans-serif;
background-color: #121212;
color: #E0E0E0;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.container {
width: 90%;
max-width: 800px;
background-color: #1E1E1E;
padding: 30px;
border-radius: 8px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
margin: 20px auto;
text-align: left;
/* Align text to the left */
font-size: 1.3em;
/* Default font size for larger screens */
}
h1 {
font-size: 2.5em;
color: #BB86FC;
margin-bottom: 20px;
text-align: center;
/* Keep the header centered */
}
.status,
.players {
margin: 20px 0;
padding: 20px;
background-color: #2E2E2E;
border: 1px solid #333;
border-radius: 5px;
font-size: 1.2em;
}
.players {
background-color: #2E7D32;
}
ul {
list-style: none;
padding: 0;
font-size: 1.2em;
/* Font size for list items */
}
ul li {
margin: 15px 0;
}
a {
color: #BB86FC;
font-size: 1.2em;
}
/* Media query for smaller screens (mobile devices) */
@media (max-width: 768px) {
.container {
font-size: 1.1em;
/* Slightly smaller font size for mobile */
}
h1 {
font-size: 2em;
/* Smaller header size on mobile */
}
.status,
.players {
font-size: 1.1em;
/* Adjust status and player text size */
}
ul {
font-size: 1.1em;
/* Adjust list item font size */
}
}
</style>
</head>
<body>
<div class="container">
<h1>Valheim Server Status</h1>
<div id="server-status" class="status">Loading server status...</div>
<div id="player-list" class="players" style="display: none;">
<h2>Connected Players</h2>
<ul id="players"></ul>
</div>
</div>
<script>
function formatDuration(durationInSeconds) {
const days = Math.floor(durationInSeconds / (24 * 3600));
const hours = Math.floor((durationInSeconds % (24 * 3600)) / 3600);
const minutes = Math.floor((durationInSeconds % 3600) / 60);
const seconds = Math.floor(durationInSeconds % 60);
let formattedTime = '';
if (days > 0) formattedTime += `${days} day${days !== 1 ? 's' : ''}, `;
if (hours > 0) formattedTime += `${hours} hour${hours !== 1 ? 's' : ''}, `;
if (minutes > 0) formattedTime += `${minutes} minute${minutes !== 1 ? 's' : ''}, `;
if (seconds > 0 || formattedTime === '') formattedTime += `${seconds} second${seconds !== 1 ? 's' : ''}`;
return formattedTime;
}
// Function to get the connected time based on duration and last status update
function getPlayerConnectedTime(durationInSeconds, lastStatusUpdate) {
const lastStatusUpdateTime = lastStatusUpdate.getTime(); // Get the last status update time in milliseconds
const connectedTime = new Date(lastStatusUpdateTime - durationInSeconds * 1000); // Convert seconds to milliseconds
return connectedTime.getTime(); // Return the timestamp in milliseconds
}
// Fetch and parse both status.json and player_info.json
async function fetchServerData() {
try {
const statusResponse = await fetch('status.json');
const statusData = await statusResponse.json();
let playerDetails = []; // Default to an empty array
try {
// Try fetching player_info.json, but skip if it fails
const playerDetailsResponse = await fetch('player_info.json');
playerDetails = await playerDetailsResponse.json();
} catch (playerError) {
console.warn("Could not fetch player_info.json, skipping player name parsing.");
}
const statusElement = document.getElementById('server-status');
const playerListElement = document.getElementById('player-list');
const playersElement = document.getElementById('players');
// Convert server's last status update timestamp to Date object
const lastStatusUpdate = new Date(statusData.last_status_update);
if (statusData.error) {
// Handle server startup timeout or error state
statusElement.innerHTML = `
<strong>Status:</strong> Server is starting up...<br>
<strong>Last Attempt:</strong> ${lastStatusUpdate.toLocaleString()}<br>
<em>The server is not ready yet. Please check again later.</em>
`;
statusElement.style.backgroundColor = '#D32F2F'; // Red background for error
} else {
// Display server status
let serverInfo = `
<strong>Server Name:</strong> ${statusData.server_name}<br>
<strong>Platform:</strong> ${statusData.platform}<br>
<strong>Player Count:</strong> ${statusData.player_count}<br>
<strong>Password Protected:</strong> ${statusData.password_protected ? 'Yes' : 'No'}<br>
<strong>Port:</strong> ${statusData.port}<br>
<strong>Steam ID:</strong> ${statusData.steam_id}<br>
<strong>Last Status Update:</strong> ${lastStatusUpdate.toLocaleString()}
`;
statusElement.innerHTML = serverInfo;
statusElement.style.backgroundColor = '#2E2E2E'; // Dark background for normal state
// Display player list if any players are connected
if (statusData.player_count > 0) {
playerListElement.style.display = 'block';
playersElement.innerHTML = ''; // Clear previous player list
statusData.players.forEach(player => {
const playerConnectedTime = getPlayerConnectedTime(player.duration, lastStatusUpdate);
// Try to find the matching player details based on connection time
const matchingPlayer = playerDetails.find(details => Math.abs(details.connected_at - playerConnectedTime / 1000) <= 10); // Allowing a 10-second window for matching
const playerName = matchingPlayer ? matchingPlayer.player_name : 'Anonymous';
const duration = formatDuration(player.duration);
const playerItem = document.createElement('li');
playerItem.innerHTML = `
<strong>Player Name:</strong> ${playerName}<br>
<strong>Duration:</strong> ${duration}<br>
<strong>Connected At:</strong> ${new Date(playerConnectedTime).toLocaleString()}
`;
playersElement.appendChild(playerItem);
});
} else {
playerListElement.style.display = 'none';
}
}
} catch (error) {
document.getElementById('server-status').innerHTML = 'Error loading server status.';
console.error('Error fetching server status:', error);
}
}
setInterval(fetchServerData, 10000);
fetchServerData();
</script>
</body>
</html>