Netplay work

This commit is contained in:
Ethan O'Brien 2023-09-18 13:02:56 -05:00
parent 54aaebb168
commit c3185b1f3b
3 changed files with 103 additions and 86 deletions

View file

@ -29,7 +29,8 @@ class EJS_GameManager {
toggleRewind: this.Module.cwrap('toggle_rewind', 'null', ['number']), toggleRewind: this.Module.cwrap('toggle_rewind', 'null', ['number']),
setRewindGranularity: this.Module.cwrap('set_rewind_granularity', 'null', ['number']), setRewindGranularity: this.Module.cwrap('set_rewind_granularity', 'null', ['number']),
toggleSlowMotion: this.Module.cwrap('toggle_slow_motion', 'null', ['number']), toggleSlowMotion: this.Module.cwrap('toggle_slow_motion', 'null', ['number']),
setSlowMotionRatio: this.Module.cwrap('set_sm_ratio', 'null', ['number']) setSlowMotionRatio: this.Module.cwrap('set_sm_ratio', 'null', ['number']),
getFrameNum: this.Module.cwrap('get_current_frame_count', 'number', [''])
} }
this.mkdir("/home"); this.mkdir("/home");
this.mkdir("/home/web_user"); this.mkdir("/home/web_user");
@ -327,6 +328,9 @@ class EJS_GameManager {
setRewindGranularity(value) { setRewindGranularity(value) {
this.functions.setRewindGranularity(value); this.functions.setRewindGranularity(value);
} }
getFrameNum() {
return this.functions.getFrameNum();
}
} }
window.EJS_GameManager = EJS_GameManager; window.EJS_GameManager = EJS_GameManager;

View file

@ -4394,7 +4394,11 @@ class EmulatorJS {
let justReset = false; let justReset = false;
this.netplay.dataMessage = (data) => { this.netplay.dataMessage = (data) => {
//console.log(data); //console.log(data);
if (data.sync === true && this.netplay.owner) {
this.netplay.sync();
}
if (data.state) { if (data.state) {
this.netplay.wait = true;
this.netplay.setLoading(true); this.netplay.setLoading(true);
this.pause(true); this.pause(true);
this.gameManager.loadState(new Uint8Array(data.state)); this.gameManager.loadState(new Uint8Array(data.state));
@ -4409,130 +4413,139 @@ class EmulatorJS {
if (data.ready && this.netplay.owner) { if (data.ready && this.netplay.owner) {
this.netplay.ready++; this.netplay.ready++;
if (this.netplay.ready === this.netplay.getUserCount()) { if (this.netplay.ready === this.netplay.getUserCount()) {
this.netplay.sendMessage({readyready:true, resetCurrentFrame: true}); this.netplay.sendMessage({readyready:true});
setTimeout(() => this.play(true), 100); this.netplay.reset();
this.play(true);
this.netplay.setLoading(false); this.netplay.setLoading(false);
this.netplay.current_frame = 0;
justReset = true;
} }
} }
if (data.readyready) { if (data.readyready) {
this.netplay.setLoading(false); this.netplay.setLoading(false);
this.netplay.current_frame = 0; this.netplay.reset();
this.play(true)
}
if (data.resetCurrentFrame) {
this.play(true); this.play(true);
this.netplay.current_frame = 0;
this.netplay.inputs = {};
} }
if (data.user_frame && this.netplay.owner) { if (data.shortPause && data.shortPause !== this.netplay.playerID) {
if (justReset) {
justReset = false;
this.netplay.current_frame = 0;
this.netplay.inputs = {};
}
this.netplay.users[data.user_frame.user] = data.user_frame.frame;
//console.log(data.user_frame.frame, this.netplay.current_frame);
}
if (data.shortPause === this.netplay.playerID) {
this.pause(true); this.pause(true);
setTimeout(() => this.play(true), 5); this.netplay.wait = true;
} else if (data.lessShortPause === this.netplay.playerID) { setTimeout(() => this.play(true), 48);
this.pause(true);
setTimeout(() => this.play(true), 10);
} }
if (data.input && this.netplay.owner) { if (data["sync-control"]) {
this.netplay.simulateInput(this.netplay.getUserIndex(data.user), data.input[0], data.input[1], true); data["sync-control"].forEach((value) => {
} let inFrame = parseInt(value.frame);
if (data.connected_input && !this.netplay.owner) { let frame = this.netplay.currentFrame;
if (!this.netplay.inputs[data.frame]) { this.netplay.inputsData[inFrame] || (this.netplay.inputsData[inFrame] = []);
this.netplay.inputs[data.frame] = []; if (!value.connected_input || value.connected_input[0] < 0) return;
} if (inFrame === frame) {
this.netplay.inputs[data.frame].push([data.connected_input[0], data.connected_input[1], data.connected_input[2]]); this.gameManager.functions.simulateInput(value.connected_input[0], value.connected_input[1], value.connected_input[2]);
}
this.netplay.inputsData[frame] || (this.netplay.inputsData[frame] = []);
if (this.netplay.owner) {
this.netplay.inputsData[frame].push(value);
this.gameManager.functions.simulateInput(value.connected_input[0], value.connected_input[1], value.connected_input[2]);
if (frame - 10 >= inFrame) {
this.netplay.wait = true;
this.pause(true);
setTimeout(() => {
this.play(true);
this.netplay.wait = false;
}, 48)
}
} else {
this.netplay.inputsData[inFrame].push(value);
if (this.netplay.inputsData[frame]) {
this.play(true);
}
if (frame + 10 <= inFrame && inFrame > this.netplay.init_frame + 100) {
this.netplay.sendMessage({shortPause:this.netplay.playerID});
}
}
});
} }
if (data.restart) { if (data.restart) {
this.gameManager.restart(); this.gameManager.restart();
this.netplay.current_frame = 0; this.netplay.reset();
this.netplay.inputs = {};
this.play(true); this.play(true);
} }
} }
this.netplay.simulateInput = (player, index, value, resp) => { this.netplay.simulateInput = (player, index, value, resp) => {
if (!this.isNetplay) return; if (!this.isNetplay) return;
if (player !== 0 && !resp) return; if (player !== 0 && !resp) return;
player = this.netplay.getUserIndex(this.netplay.playerID)
const frame = this.netplay.currentFrame;
if (this.netplay.owner) { if (this.netplay.owner) {
const frame = this.netplay.current_frame; if (!this.netplay.inputsData[frame]) {
this.gameManager.functions.simulateInput(player, index, value); this.netplay.inputsData[frame] = [];
this.netplay.sendMessage({ }
this.netplay.inputsData[frame].push({
frame: frame, frame: frame,
connected_input: [player, index, value] connected_input: [player, index, value]
}); })
this.gameManager.functions.simulateInput(player, index, value);
} else { } else {
this.netplay.sendMessage({ this.netplay.sendMessage({
user: this.netplay.playerID, "sync-control": [{
input: [index, value] frame: frame,
}); connected_input: [player, index, value]
}]
})
} }
} }
this.netplay.sendMessage = (data) => { this.netplay.sendMessage = (data) => {
this.netplay.socket.emit("data-message", data); this.netplay.socket.emit("data-message", data);
} }
this.netplay.reset = () => {
this.netplay.init_frame = this.netplay.currentFrame;
this.netplay.inputsData = {};
}
//let fps; //let fps;
//let lastTime; //let lastTime;
this.netplay.init_frame = 0;
this.netplay.currentFrame = 0;
this.netplay.inputsData = {};
this.Module.postMainLoop = () => { this.Module.postMainLoop = () => {
//const newTime = window.performance.now(); //const newTime = window.performance.now();
//fps = 1000 / (newTime - lastTime); //fps = 1000 / (newTime - lastTime);
//console.log(fps); //console.log(fps);
//lastTime = newTime; //lastTime = newTime;
if (!this.isNetplay || this.paused) return;
this.netplay.current_frame++; //frame syncing - working
//control syncing - broken
if (!this.isNetplay) return;
this.netplay.currentFrame = parseInt(this.gameManager.getFrameNum()) - this.netplay.init_frame;
if (this.netplay.owner) { if (this.netplay.owner) {
for (const k in this.netplay.users) { let to_send = [];
if (this.netplay.getUserIndex(k) === -1) { for (let i=this.netplay.currentFrame-1; i<this.netplay.currentFrame; i++) {
delete this.netplay.users[k]; this.netplay.inputsData[i] ? this.netplay.inputsData[i].forEach((value) => {
continue; to_send.push(value);
} }) : to_send.push({frame: i});
const diff = this.netplay.current_frame - this.netplay.users[k];
//console.log(diff);
if (Math.abs(diff) > 75) {
this.netplay.sync();
return;
}
//this'll be adjusted if needed
if (diff < 0) {
this.netplay.sendMessage({
lessShortPause: k
})
}
if (diff < 5) {
this.netplay.sendMessage({
shortPause: k
})
} else if (diff > 30) {
this.pause(true);
setTimeout(() => this.play(true), 10);
} else if (diff > 10) {
this.pause(true);
setTimeout(() => this.play(true), 5);
}
} }
this.netplay.sendMessage({"sync-control": to_send});
} else { } else {
this.netplay.sendMessage({ if (this.netplay.currentFrame <= 0 || this.netplay.inputsData[this.netplay.currentFrame]) {
user_frame: { this.netplay.wait = false;
user: this.netplay.playerID, this.play();
frame: this.netplay.current_frame this.netplay.inputsData[this.netplay.currentFrame].forEach((value) => {
} console.log(value);
}); if (!value.connected_input) return;
for (const k in this.netplay.inputs) { this.gameManager.functions.simulateInput(value.connected_input[0], value.connected_input[1], value.connected_input[2]);
if (k <= this.netplay.current_frame) { })
this.netplay.inputs[k].forEach(data => { } else if (!this.netplay.syncing) {
this.gameManager.functions.simulateInput(data[0], data[1], data[2]); console.log("sync");
}) this.pause(true);
delete this.netplay.inputs[k]; this.netplay.sendMessage({sync:true});
} this.netplay.syncing = true;
} }
} }
if (this.netplay.currentFrame % 100 === 0) {
Object.keys(this.netplay.inputsData).forEach(value => {
if (value < this.netplay.currentFrame - 50) {
this.netplay.inputsData[value] = null;
delete this.netplay.inputsData[value];
}
})
}
} }
this.netplay.updateList = { this.netplay.updateList = {

File diff suppressed because one or more lines are too long