diff --git a/src/api.ts b/src/api.ts index 1ebe7be..99ac2a7 100644 --- a/src/api.ts +++ b/src/api.ts @@ -106,38 +106,36 @@ class APIConnection let data: Object = null; let resp: Object = null; - let packets = message.split('\0') - message = packets[0]; + let packets = message.split('\0'); + + info("OnDataReceived ", message.length); + info("Buffer:", this.buffer.length); + info("packets.length:", packets.length); + + for(let i=0; i 1) { - packets = packets.slice(1); - message = packets.join('\0'); - if(message.length > 1) { - this.onData(message); + try { + info(this.name+" received data: ", data); + resp = this.callback(data); + } catch(e) { + printException('error handling '+this.name+' request: ' + message, e); } } } diff --git a/src/base.ts b/src/base.ts index a80d9ff..340cc22 100644 --- a/src/base.ts +++ b/src/base.ts @@ -167,8 +167,12 @@ function runNextTick(func: Function) { function ifPaused(whenPaused: () => void, whenUnpaused: () => void) { var wasPaused = context.paused; - if(wasPaused) whenPaused(); - else whenUnpaused(); + if(wasPaused && whenPaused) { + whenPaused(); + } + else if(!wasPaused && whenUnpaused) { + whenUnpaused(); + } return wasPaused; } diff --git a/src/gui/archipelagoWindow.ts b/src/gui/archipelagoWindow.ts index 27e9e22..1832e03 100644 --- a/src/gui/archipelagoWindow.ts +++ b/src/gui/archipelagoWindow.ts @@ -7,26 +7,32 @@ function archipelagoGui(){ let y = 0; var onStart = function() { - console.log('This is where we connect to Archipelago and set up the game.'); - //TODO: Get seed from Archipelago - setGlobalSeed(Math.floor(Math.random() * 1000000));//Maybe someday I'll allow custom seeds - //No need for research, since we're using a different system entirely for that - settings.rando_research = false; - //Crowd control has a lot of options that would most likely break Archipelago. We're going to disable both at once until further notice. - archipelago_settings.deathlink_timeout = false; - //We're going to track the objectives ourselves instead - scenario.objective.type = "haveFun"; - archipelago_settings.started = true; - saveArchipelagoProgress();//Save the settings to our Archipelago tracker - // we need to unpause the game in order for the next tick to run - UnpauseGame(); - runNextTick(function() { - initRando(); - if(global_settings.auto_pause) { - PauseGame(); - } - createChangesWindow(); - }); + try{ + console.log('This is where we connect to Archipelago and set up the game.'); + //TODO: Get seed from Archipelago + setGlobalSeed(Math.floor(Math.random() * 1000000));//Maybe someday I'll allow custom seeds + //No need for research, since we're using a different system entirely for that + settings.rando_research = false; + //Crowd control has a lot of options that would most likely break Archipelago. We're going to disable both at once until further notice. + archipelago_settings.deathlink_timeout = false; + //We're going to track the objectives ourselves instead + scenario.objective.type = "haveFun"; + archipelago_settings.started = true; + saveArchipelagoProgress();//Save the settings to our Archipelago tracker + // we need to unpause the game in order for the next tick to run + UnpauseGame(); + runNextTick(function() { + initRando(); + if(global_settings.auto_pause) { + PauseGame(); + } + createChangesWindow(); + }); + } + catch(e){ + printException("Error in onStart (archipelagoWindow):", e); + throw e; + } } var window = ui.openWindow({ diff --git a/src/modules/archipelago.ts b/src/modules/archipelago.ts index beed685..feebac4 100644 --- a/src/modules/archipelago.ts +++ b/src/modules/archipelago.ts @@ -9,10 +9,10 @@ class RCTRArchipelago extends ModuleBase { if(!settings.rando_archipelago) return; self.RemoveItems();//Removes everything from the invented items list. They'll be added back when Archipelago sends items - let timeout = archipelago_settings.multiworld_games.length * 6000; + let timeout = archipelago_settings.multiworld_games.length * 10000; context.setTimeout(() => {archipelago_send_message("Sync");}, 1000); context.setTimeout(() => {archipelago_send_message("GetDataPackage");}, 2500);//We have to stagger these to not break the connection. - context.setTimeout(() => {archipelago_send_message("LocationScouts");}, 6000 + timeout); + context.setTimeout(() => {archipelago_send_message("LocationScouts");}, 10000 + timeout); context.setTimeout(() => {self.SetPostGenerationSettings();}, 6500+ timeout);//Wait a few seconds for the other settings to do their thing //Setting rules for Archipelago, dictated by the YAML var setRules = function(){ diff --git a/src/modules/archipelagoConnection.ts b/src/modules/archipelagoConnection.ts index d2a36c8..1ef8b8a 100644 --- a/src/modules/archipelagoConnection.ts +++ b/src/modules/archipelagoConnection.ts @@ -18,96 +18,106 @@ var send_timeout = false; //For plugin side sends var spam_timeout = false; //For user side sends function archipelago_send_message(type: string, message?: any) { - console.log(connection.buffer.length); - if (connection.buffer.length == 0){ - if (!send_timeout){ - switch(type){//Gotta fill these in as we improve crud - case "Connect": - console.log({cmd: "Connect", password: message.password, game: "OpenRCT2", name: message.name, uuid: message.name + ": OpenRCT2", version: {major: 0, minor: 4, build: 1}, item_handling: 0b111, tags: (archipelago_settings.deathlink) ? ["DeathLink"] : [], slot_data: true}); - break; - case "ConnectUpdate": - console.log({cmd: "ConnectUpdate", tags: (archipelago_settings.deathlink) ? ["DeathLink"] : []}) - break; - case "Sync": - connection.send({cmd: "Sync"}); - break; - case "LocationChecks": - var checks = [];//List of unlocked locations - for (let i = 0; i < message.length; i++){ - checks.push(message[i].LocationID + 2000000);//OpenRCT2 has reserved the item ID space starting at 2000000 - } - connection.send({cmd: "LocationChecks", locations: checks}); - break; - case "LocationScouts": - var wanted_locations = []; - for(let i = 0; i < archipelago_location_prices.length; i++){ - wanted_locations.push(2000000 + i); - } - connection.send({cmd: "LocationScouts", locations: wanted_locations, create_as_hint: 0}); - break; - case "LocationHints": - connection.send({cmd: "LocationScouts", locations: message, create_as_hint: 2}); - break; - case "StatusUpdate": - connection.send({cmd: "StatusUpdate", status: message});//CLIENT_UNKNOWN = 0; CLIENT_CONNECTED = 5; CLIENT_READY = 10; CLIENT_PLAYING = 20; CLIENT_GOAL = 30 - break; - case "Say": - const regex = /peck/gi; - message = message.replace(regex, 'p*ck'); - console.log({cmd: "Say", text: message}); - connection.send({cmd: "Say", text: message}); - break; - case "GetDataPackage": - var self = this; - var requested_games = []; - var timeout = 1; - if (archipelago_multiple_requests){ - for(let i = 0; i < archipelago_settings.multiworld_games.length; i++){ - requested_games.push(archipelago_settings.multiworld_games[i]); - console.log(requested_games); - if (requested_games.length == 1){ - let games = requested_games; - if(games)//Why is it trying to send empty lists of games? - context.setTimeout(() => { - connection.send({cmd: "GetDataPackage", games: games}); archipelago_games_requested += 1; - }, timeout);//console.log("Sending the following games for IDs: " + requested_games); - timeout += 5000; - requested_games = []; - } - } - // if (requested_games){//request any remaining games - // let games = requested_games; - // context.setTimeout(() => {connection.send({cmd: "GetDataPackage", games: games}); archipelago_games_requested += games.length;}, timeout); - // } - } - // else{ - // connection.send({cmd: "GetDataPackage", games: archipelago_settings.multiworld_games}); - // archipelago_games_requested += archipelago_settings.multiworld_games.length; - // } - break; - case "Bounce": - if(message.tag == "DeathLink"){ - connection.send({cmd: "Bounce", tags: ["DeathLink"], data: {time: Math.round(+new Date()/1000), cause: message.ride + " has crashed!", source: archipelago_settings.player[0]}}); - } - break; - case "Get": - connection.send({cmd: "Get", keys: []}); - break; - case "Set": - break; - case "SetNotify": - break; + try { + console.log(connection.buffer.length); + if (connection.buffer.length == 0){ + if (!send_timeout){ + archipelago_select_message(type, message); + send_timeout = true; + context.setTimeout(() => {send_timeout = false;}, 3000); + } + else{ + context.setTimeout(() => {archipelago_send_message(type,message);}, 3000); } - send_timeout = true; - context.setTimeout(() => {send_timeout = false;}, 3000); - } - else{ - context.setTimeout(() => {archipelago_send_message(type,message);}, 3000); } } - else{ - console.log("Receiving message. Will send once complete."); - context.setTimeout(() => {archipelago_send_message(type,message);}, 3000); + catch(e) { + printException('error sending '+this.name, e); + throw(e); + } + // else{ + // console.log("Receiving message. Will send once complete."); + // context.setTimeout(() => {archipelago_send_message(type,message);}, 3000); + // } +} + +function archipelago_select_message(type: string, message?: any){ + switch(type){ + case "Connect": + console.log({cmd: "Connect", password: message.password, game: "OpenRCT2", name: message.name, uuid: message.name + ": OpenRCT2", version: {major: 0, minor: 4, build: 1}, item_handling: 0b111, tags: (archipelago_settings.deathlink) ? ["DeathLink"] : [], slot_data: true}); + break; + case "ConnectUpdate": + console.log({cmd: "ConnectUpdate", tags: (archipelago_settings.deathlink) ? ["DeathLink"] : []}) + break; + case "Sync": + connection.send({cmd: "Sync"}); + break; + case "LocationChecks": + var checks = [];//List of unlocked locations + for (let i = 0; i < message.length; i++){ + checks.push(message[i].LocationID + 2000000);//OpenRCT2 has reserved the item ID space starting at 2000000 + } + connection.send({cmd: "LocationChecks", locations: checks}); + break; + case "LocationScouts": + var wanted_locations = []; + for(let i = 0; i < archipelago_location_prices.length; i++){ + wanted_locations.push(2000000 + i); + } + connection.send({cmd: "LocationScouts", locations: wanted_locations, create_as_hint: 0}); + break; + case "LocationHints": + connection.send({cmd: "LocationScouts", locations: message, create_as_hint: 2}); + break; + case "StatusUpdate": + connection.send({cmd: "StatusUpdate", status: message});//CLIENT_UNKNOWN = 0; CLIENT_CONNECTED = 5; CLIENT_READY = 10; CLIENT_PLAYING = 20; CLIENT_GOAL = 30 + break; + case "Say": + const regex = /peck/gi; + message = message.replace(regex, 'p*ck'); + console.log({cmd: "Say", text: message}); + connection.send({cmd: "Say", text: message}); + break; + case "GetDataPackage": + var self = this; + var requested_games = []; + var timeout = 1; + if (archipelago_multiple_requests){ + for(let i = 0; i < archipelago_settings.multiworld_games.length; i++){ + requested_games.push(archipelago_settings.multiworld_games[i]); + console.log(requested_games); + if (requested_games.length == 1){ + let games = requested_games; + if(games)//Why is it trying to send empty lists of games? + context.setTimeout(() => { + connection.send({cmd: "GetDataPackage", games: games}); archipelago_games_requested += 1; + }, timeout);//console.log("Sending the following games for IDs: " + requested_games); + timeout += 9000; + requested_games = []; + } + } + // if (requested_games){//request any remaining games + // let games = requested_games; + // context.setTimeout(() => {connection.send({cmd: "GetDataPackage", games: games}); archipelago_games_requested += games.length;}, timeout); + // } + } + // else{ + // connection.send({cmd: "GetDataPackage", games: archipelago_settings.multiworld_games}); + // archipelago_games_requested += archipelago_settings.multiworld_games.length; + // } + break; + case "Bounce": + if(message.tag == "DeathLink"){ + connection.send({cmd: "Bounce", tags: ["DeathLink"], data: {time: Math.round(+new Date()/1000), cause: message.ride + " has crashed!", source: archipelago_settings.player[0]}}); + } + break; + case "Get": + connection.send({cmd: "Get", keys: []}); + break; + case "Set": + break; + case "SetNotify": + break; } }