Skip to content

Commit

Permalink
Networking Updates
Browse files Browse the repository at this point in the history
  • Loading branch information
Crazycolbster committed May 6, 2024
1 parent 13d167a commit 262b498
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 138 deletions.
52 changes: 25 additions & 27 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<packets.length; i++) {
let message = packets[i];
if(message.length == 0) continue;

// try
try {
data = JSON.parse(message);
this.buffer = "";
} catch(e) {
try {
this.buffer += message;
data = JSON.parse(this.buffer);
data = JSON.parse(message);
this.buffer = "";
} catch(e) {
try {
this.buffer += message;
data = JSON.parse(this.buffer);
this.buffer = "";
}
catch(e) {
printException('error parsing '+this.name, e);//+' request JSON: ' + this.buffer, e);
continue;
}
}
catch(e) {
printException('error parsing '+this.name+' request JSON: ' + message, e);
return;
}
}

try {
info(this.name+" received data: ", data);
resp = this.callback(data);
// this.send(resp);
} catch(e) {
printException('error handling '+this.name+' request: ' + message, e);
}

if(packets.length > 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);
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
46 changes: 26 additions & 20 deletions src/gui/archipelagoWindow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
4 changes: 2 additions & 2 deletions src/modules/archipelago.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(){
Expand Down
184 changes: 97 additions & 87 deletions src/modules/archipelagoConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down

0 comments on commit 262b498

Please sign in to comment.