Skip to content

Commit 228763a

Browse files
committed
added players sync
1 parent 581565d commit 228763a

File tree

5 files changed

+276
-82
lines changed

5 files changed

+276
-82
lines changed

src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,11 @@ router.use(helmet());
188188
Joi,
189189
network
190190
);
191+
(await import("./routes/teams/POST_Playerlist.js")).initRoutes(
192+
router,
193+
Joi,
194+
network
195+
);
191196

192197
// Init PUT Routes for the API
193198
(await import("./routes/teams/PUT_TeamHasBuildTeamToolsInstalled.js")).initRoutes(
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { Router } from "express";
2+
import Network, { BuildTeamIdentifier } from "../../struct/core/network.js";
3+
4+
export async function initRoutes(app: Router, joi: any, network: Network) {
5+
6+
app.post('/api/teams/:apikey/playerlist', async function (req, res) {
7+
8+
// Validate that the API key is a valid GUID
9+
if(!await network.validateAPIKey(req, res))
10+
return;
11+
12+
const buildTeam = await network.getBuildTeam(req.params.apikey, BuildTeamIdentifier.APIKey);
13+
14+
if(buildTeam == null) {
15+
res.status(400).send({ error: 'Build Team not found' });
16+
return;
17+
}
18+
19+
// Validate the parameters with joi
20+
21+
// Schema for a single UUID and username pair
22+
const uuidUsernameSchema = joi.array().ordered(
23+
joi.string().guid({ version: 'uuidv4' }), // Validates a UUID (version 4)
24+
joi.string() // Validates a simple string for the username
25+
).length(2);
26+
27+
// Schema for the main array, containing multiple UUID-username pairs
28+
const schema = joi.array().items(uuidUsernameSchema);
29+
30+
const validation = schema.validate(req.body);
31+
32+
// If the validation failed, return an error
33+
if(validation.error != null){
34+
res.status(400).send({success: false, error: validation.error.details[0].message});
35+
return;
36+
}
37+
38+
39+
const result = await buildTeam.updatePlayerlist(req.body);
40+
41+
42+
43+
// If the playerlist was not updated, return an error
44+
if(result == false){
45+
res.status(400).send({success: false, error: 'An error occurred while updating the playerlist'});
46+
return;
47+
}else{
48+
// Return the order id to the client
49+
res.setHeader('Content-Type', 'application/json');
50+
res.send({success: true})
51+
}
52+
})
53+
}

src/struct/core/buildteam.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,15 @@ export default class BuildTeam {
2828
private static readonly SERVER_UPDATE_INTERVAL: number = 60 * 24; // 24 hours
2929
private static readonly FTP_CONFIGURATION_UPDATE_INTERVAL: number = 60 * 24; // 24 hours
3030
private static readonly BUILD_TEAM_INFO_UPDATE_INTERVAL: number = 60 * 1; // 1 hour
31+
private static readonly PLAYER_LIST_CLEAR_INTERVAL: number = 60 * 1; // 1 hours
3132

3233
private apiKey: string;
3334
private buildTeamID: string | null = null;
3435
private network: Network;
3536
private psDatabase: DatabaseHandler
3637
private nwDatabase: DatabaseHandler
38+
private playerList: any[] = [];
39+
private lastPlayerListUpdate: Date | null = null;
3740

3841
private psBuildTeamID: string | null = null;
3942
private psCities: Map<number, any[]> = new Map() // Map<country_id, city>
@@ -78,6 +81,15 @@ export default class BuildTeam {
7881

7982
if(this.psFTPConfiguration != null && this.network.getUpdateCacheTicks() % BuildTeam.FTP_CONFIGURATION_UPDATE_INTERVAL == 0)
8083
this.psFTPConfiguration.clear();
84+
85+
// If the last player list update is older than the player list clear interval, clear the player list
86+
if(this.playerList != null && this.lastPlayerListUpdate != null && this.network.getUpdateCacheTicks() % BuildTeam.PLAYER_LIST_CLEAR_INTERVAL == 0){
87+
const timeDifference = (new Date().getTime() - this.lastPlayerListUpdate.getTime()) / 1000;
88+
if(timeDifference > BuildTeam.PLAYER_LIST_CLEAR_INTERVAL){
89+
this.playerList = [];
90+
this.lastPlayerListUpdate = null;
91+
}
92+
}
8193
}
8294

8395
// Resets the cache for the build team
@@ -87,6 +99,8 @@ export default class BuildTeam {
8799
this.psCountries.clear();
88100
this.psServers.clear();
89101
this.psFTPConfiguration.clear();
102+
this.playerList = [];
103+
this.lastPlayerListUpdate = null;
90104
}
91105

92106
async loadBuildTeamData(){
@@ -594,6 +608,43 @@ export default class BuildTeam {
594608

595609

596610

611+
/* ======================================= */
612+
/* Playerlist */
613+
/* ======================================= */
614+
615+
616+
/** Updates the playerlist of the build team.
617+
*
618+
* @param players The list of players
619+
*
620+
* @returns Returns true if the playerlist was updated successfully, otherwise false.
621+
**/
622+
async updatePlayerlist(players: any[]) {
623+
// Validate that the build team id is loaded
624+
if(this.buildTeamID == null)
625+
await this.loadBuildTeamData();
626+
if(this.buildTeamID == null)
627+
return false;
628+
629+
// Take the data that is needed for the BuildTeamOnlinePlayers table
630+
const tempArray: any[] = [];
631+
632+
players.forEach((subArray) => {
633+
tempArray.push([subArray[0], subArray[1], this.buildTeamID]);
634+
});
635+
636+
this.lastPlayerListUpdate = new Date();
637+
this.playerList = tempArray;
638+
639+
return true;
640+
}
641+
642+
getPlayerList() {
643+
return this.playerList;
644+
}
645+
646+
647+
597648

598649
/* ======================================= */
599650
/* PlotSystem */

src/struct/core/network.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ export default class Network {
115115
if (isStarting == true) bar?.tick();
116116
}
117117

118+
this.syncPlayerList();
119+
118120
this.updateCacheTicks++;
119121

120122
if(this.updateCacheTicks >= Number.MAX_SAFE_INTEGER - 100)
@@ -437,7 +439,15 @@ export default class Network {
437439
return json.display_name;
438440
}
439441

442+
async syncPlayerList(): Promise<number | false>{
443+
let globalPlayerList: any[] = [];
444+
445+
// Create a two dimensional array with one array for each player
446+
for (const buildTeam of this.buildTeams.values())
447+
globalPlayerList = globalPlayerList.concat(buildTeam.getPlayerList());
440448

449+
return this.syncPlayerListInDatabase(globalPlayerList);
450+
}
441451

442452

443453

@@ -579,4 +589,32 @@ export default class Network {
579589
const SQL = "SELECT * FROM BuildTeamWarpGroups";
580590
return await this.networkDatabase.query(SQL);
581591
}
592+
593+
594+
/* =================================================== */
595+
/* DATABASE POST REQUESTS */
596+
/* =================================================== */
597+
598+
private async syncPlayerListInDatabase(playerList: any[]): Promise<number | false> {
599+
try {
600+
// Truncate the table first
601+
await this.networkDatabase.query("TRUNCATE TABLE BuildTeamOnlinePlayers");
602+
603+
// Insert new data if available
604+
if (playerList && playerList.length > 0) {
605+
const placeholders = playerList.map(() => "(?, ?, ?)").join(", ");
606+
const flatValues = playerList.flat();
607+
const insertSQL = `INSERT INTO BuildTeamOnlinePlayers (UUID, Name, BuildTeam) VALUES ${placeholders}`;
608+
const insertResult = await this.networkDatabase.query(insertSQL, flatValues);
609+
610+
if (insertResult.affectedRows > 0)
611+
return insertResult.affectedRows;
612+
}
613+
} catch (error) {
614+
console.error(error);
615+
return false;
616+
}
617+
618+
return false;
619+
}
582620
}

0 commit comments

Comments
 (0)