· 6 years ago · Jun 09, 2019, 12:22 PM
1
2var PlayerGameData = require('../../models/savedata');
3var CheckAccessKey = require('./shared/check_access_key');
4var Heartbeat = require('../heartbeat');
5
6var ERROR_API_KEY_NOT_REGISTERED = "No api_access_key found for api_key given. Please use a registered api_key or register a new api_key via your games web portal" ;
7var ERROR_ACCESS_KEY_INVALID = "The api_access_key given does not match that found on the server for the given api_key. Please check your access key used against that found in your games web portal";
8var ERROR_LOAD_STEAMIDS_INVALID = "The requested steamids were sent with an invalid format. Please send with the correct format";
9var ERROR_INVALID_ERROR = "This error should not have been reached and the only error is that this is being shown";
10
11
12module.exports.saveMany = function(req,res){
13
14 //var data = JSON.parse(req.body.data); //had to disable this so that we can send in fake requests with postman
15 var data = req.body.data;
16 if(data !== null && typeof data === 'object'){
17 }else{
18 data = JSON.parse(req.body.data)
19 }
20
21 if(data == null){
22 console.log("Null data sent to server");
23 res.send({s: false, m: "Null data sent to server"});
24 return;
25 };
26
27 var api_access_key = req.body.aak;
28 var api_key = req.body.api_key;
29 var match_id = req.body._matchid
30 var check = CheckAccessKey(api_key, api_access_key);
31 var success = check[0];
32 var eMsg = check[1];
33
34 if(success !== true){
35 console.log(eMsg);
36 res.send({s: false, m: eMsg});
37 return;
38 }
39
40 //timeplayed should be added to saveobject for active slot so that it happens alongside any new saves
41
42 res.res_info = {};
43 for(var steam_id in data){
44 res.res_info[steam_id] = {
45 success: false,
46 complete: false,
47 };
48 }
49
50 var players_in_game = []
51 for(var steam_id in data){
52 players_in_game.push(steam_id);
53 FindAndUpdatePlayerData(req, res, api_key, steam_id, data[steam_id]);
54 }
55 if(data.length == 0){
56 res.send({s: false, m: "Received an empty array when we expected {steamid: character_data_array}"})
57 }
58
59 //Pulse heartbeat
60 Heartbeat.pulse(match_id, players_in_game)
61};
62
63
64function FindAndUpdatePlayerData(req, res, api_key, steam_id, player_data){
65
66 //steamid actually has a anti-trailing _, this needs to be removed before its used to search
67 PlayerGameData.findOne({api_key: api_key, steam_id: steam_id}).exec(function(error, storage_data){
68 if(error != null){
69 console.log(error);
70
71 //Modify the response_info object to announce the failure of this merge
72 res.res_info[res_index].success = false;
73 res.res_info[res_index].complete = true;
74 UserUpdateComplete(req,res,res.res_info);
75 return;
76 }
77
78 //if the object doesn't yet exist, create it before deciding to operate it
79 if(!storage_data){
80 storage_data = new PlayerGameData();
81 storage_data.api_key = api_key;
82 storage_data.steam_id = steam_id;
83 }
84
85 // globals data shared between all characters
86 if(player_data.player){
87 console.log("player data was sent")
88 console.log(player_data.player)
89 for(var sys_name in player_data.player){
90 storage_data.player_data[sys_name] = player_data.player[sys_name];
91 }
92 }
93
94
95
96
97 //re-order so the saves are handled sequentially in order of charIndex (so we don't get weird overwrite issues)
98 //additionally, remove 1 from all charIndex before being handled directly by server, as lua is 1-indexed and js is 0indexed
99 //will need to add 1 to all charIndex before returning info to client.
100
101 //need to consider that we should return ALL the new character indexes to the client, not just those related to the characters that were sent in.
102 var ordered_player_data = [];
103 for(var index in player_data.characters){
104 var slot_index = player_data.characters[index].meta.CharIndex - 1;
105 ordered_player_data[slot_index] = player_data.characters[index];
106 }
107
108 for(var slot_index in ordered_player_data){
109 var char_data = ordered_player_data[slot_index].data;
110 var meta = ordered_player_data[slot_index].meta;
111 var time_played = meta.TimePlayed;
112
113 //If the character exists
114 if(storage_data.char_data[slot_index]){
115 for(var sys_name in char_data){
116 storage_data.char_data[slot_index][sys_name] = char_data[sys_name]
117 }
118 }
119 else{
120 storage_data.char_data.push(char_data);
121 //todo: make sure that the player can't send a save for slot (example: 5)
122 //todo: if they do not have any OR are not sending any data for empty slots beforehand
123 //todo: return index to game so that the SDO/LDO can register it
124 }
125
126 //Will always have a default value due to the schema
127 storage_data.char_data[slot_index].TimePlayed += time_played;
128 storage_data.player_data.TimePlayed += time_played;
129 }
130
131 var combined_game_and_server_data = [];
132
133 //after the indexes have been updated, we can remove chardata if necessary.
134 //if char data is deleted, we need to send back a command to the game to update the char_indexes.
135 var index_modifications = {};
136 var edited_slots = 0;
137 for (var slot_index in storage_data.char_data.toObject()) {
138 var sent_data = ordered_player_data[slot_index]
139
140 if ((sent_data) && (sent_data.meta) && (sent_data.meta.del == true)) {
141 //delete one slot from the saved data, modify slot we change by 1 for each slot we change (as the other slots will get moved)
142 storage_data.char_data.splice(slot_index - edited_slots, 1);
143 edited_slots += 1;
144 } else {
145 //modify the stored index by +1 to return it to a format suitable for lua
146 var fixed_index = new Number(slot_index) + 1
147 index_modifications[fixed_index] = {
148 new: (fixed_index - edited_slots),
149 }
150 }
151
152 }
153 if(edited_slots > 0){
154 res.res_info[steam_id].edited_slots = index_modifications
155 }
156
157
158 var promise = storage_data.save();
159 HandleUpdatePromise(req,res, promise, steam_id)
160 //processSaveDiff(req, res, existing, api_key, steam_id, diff);
161 })
162}
163
164
165
166function HandleUpdatePromise(req,res,promise, steam_id){
167 promise.then(function() {
168 res.res_info[steam_id].success = true;
169 res.res_info[steam_id].complete = true;
170 UserUpdateComplete(req, res, res.res_info)
171 });
172}
173
174function UserUpdateComplete(req,res,response_info){
175
176 var ret_data = {
177 s: true, //the update was successful
178 c: {} //additional commands table
179 };
180
181 for(var steamid in response_info){
182 if(response_info[steamid].complete == false){
183 return;
184 }
185
186 //Did this steamid have any slot changes to their data
187 if(response_info[steamid].edited_slots){
188 ret_data.c.edited_slots = ret_data.c.edited_slots || {};
189 ret_data.c.edited_slots[steamid] = response_info[steamid].edited_slots
190 }
191 }
192
193 //add delay to next save being sent todo: Make the request based on server load
194 //ret_data.c.d = Math.floor((Math.random() * 10) + 1);
195
196
197 res.send(ret_data);
198};