mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2024-11-14 21:37:42 -07:00
base for forwarding input to clients
This commit is contained in:
parent
1d135bc0a5
commit
79494fad5e
@ -19,6 +19,9 @@
|
||||
#ifndef INPUT_H
|
||||
#define INPUT_H
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace Input
|
||||
|
@ -19,10 +19,17 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <queue>
|
||||
|
||||
#include <enet/enet.h>
|
||||
|
||||
#include "NDS.h"
|
||||
#include "main.h"
|
||||
#include "Netplay.h"
|
||||
#include "Input.h"
|
||||
|
||||
|
||||
extern EmuThread* emuThread;
|
||||
|
||||
|
||||
namespace Netplay
|
||||
@ -34,6 +41,14 @@ bool IsHost;
|
||||
ENetHost* Host;
|
||||
ENetPeer* Peer;
|
||||
|
||||
struct InputFrame
|
||||
{
|
||||
u32 FrameNum;
|
||||
u32 KeyMask;
|
||||
};
|
||||
|
||||
std::queue<InputFrame> InputQueue;
|
||||
|
||||
|
||||
bool Init()
|
||||
{
|
||||
@ -119,26 +134,158 @@ void StartClient()
|
||||
}
|
||||
|
||||
|
||||
void StartGame()
|
||||
{
|
||||
if (!IsHost)
|
||||
{
|
||||
printf("?????\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// tell remote peers to start game
|
||||
u8 cmd[1] = {0x01};
|
||||
ENetPacket* pkt = enet_packet_create(cmd, sizeof(cmd), ENET_PACKET_FLAG_RELIABLE);
|
||||
enet_host_broadcast(Host, 0, pkt);
|
||||
|
||||
// start game locally
|
||||
NDS::Start();
|
||||
emuThread->emuRun();
|
||||
}
|
||||
|
||||
|
||||
void ProcessFrame()
|
||||
{
|
||||
bool block = false;
|
||||
if (emuThread->emuIsRunning())
|
||||
{
|
||||
if (IsHost)
|
||||
{
|
||||
// TODO: prevent the clients from running too far behind
|
||||
}
|
||||
else
|
||||
{
|
||||
// block if we ran out of input frames
|
||||
// TODO: in this situation, make sure we do receive an input frame
|
||||
// or if we don't after X time, handle it gracefully
|
||||
|
||||
if (InputQueue.empty())
|
||||
block = true;
|
||||
}
|
||||
}
|
||||
block=false;
|
||||
|
||||
ENetEvent event;
|
||||
while (enet_host_service(Host, &event, 0) > 0)
|
||||
while (enet_host_service(Host, &event, block ? 5000 : 0) > 0)
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case ENET_EVENT_TYPE_CONNECT:
|
||||
printf("client connected %08X %d\n", event.peer->address.host, event.peer->address.port);
|
||||
Peer = event.peer;
|
||||
break;
|
||||
|
||||
case ENET_EVENT_TYPE_DISCONNECT:
|
||||
printf("client disconnected %08X %d\n", event.peer->address.host, event.peer->address.port);
|
||||
Peer = nullptr;
|
||||
break;
|
||||
|
||||
case ENET_EVENT_TYPE_RECEIVE:
|
||||
printf("received shit\n");
|
||||
{
|
||||
if (event.packet->dataLength < 1)
|
||||
{
|
||||
printf("?????\n");
|
||||
break;
|
||||
}
|
||||
|
||||
u8* data = (u8*)event.packet->data;
|
||||
switch (data[0])
|
||||
{
|
||||
case 0x01: // start game
|
||||
NDS::Start();
|
||||
emuThread->emuRun();
|
||||
break;
|
||||
|
||||
case 0x02: // input frame
|
||||
{
|
||||
if (event.packet->dataLength != (sizeof(InputFrame)+1))
|
||||
break;
|
||||
|
||||
InputFrame frame;
|
||||
memcpy(&frame, &data[1], sizeof(InputFrame));
|
||||
InputQueue.push(frame);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessInput()
|
||||
{
|
||||
// netplay input processing
|
||||
//
|
||||
// N = current frame #
|
||||
// L = amount of lag frames
|
||||
//
|
||||
// host side:
|
||||
// we take the current input (normally meant for frame N)
|
||||
// and delay it to frame N+L
|
||||
//
|
||||
// client side:
|
||||
// we receive input from the host
|
||||
// apply each input to the frame it's assigned to
|
||||
// before running a frame, we need to wait to have received input for it
|
||||
// TODO: alert host if we are running too far behind
|
||||
|
||||
if (IsHost)
|
||||
{
|
||||
u32 lag = 4; // TODO: make configurable!!
|
||||
|
||||
InputFrame frame;
|
||||
frame.FrameNum = NDS::NumFrames + lag;
|
||||
frame.KeyMask = Input::InputMask;
|
||||
// TODO: touchscreen input and other shit!
|
||||
|
||||
InputQueue.push(frame);
|
||||
|
||||
u8 cmd[1+sizeof(InputFrame)];
|
||||
cmd[0] = 0x02;
|
||||
memcpy(&cmd[1], &frame, sizeof(InputFrame));
|
||||
ENetPacket* pkt = enet_packet_create(cmd, sizeof(cmd), ENET_PACKET_FLAG_RELIABLE);
|
||||
enet_host_broadcast(Host, 0, pkt);
|
||||
}
|
||||
|
||||
if (InputQueue.empty())
|
||||
{
|
||||
printf("Netplay: BAD! INPUT QUEUE EMPTY\n");
|
||||
return;
|
||||
}
|
||||
|
||||
InputFrame& frame = InputQueue.front();
|
||||
|
||||
if (frame.FrameNum < NDS::NumFrames)
|
||||
{
|
||||
printf("Netplay: BAD! LAGGING BEHIND\n");
|
||||
while (frame.FrameNum < NDS::NumFrames)
|
||||
{
|
||||
if (InputQueue.size() < 2) break;
|
||||
InputQueue.pop();
|
||||
frame = InputQueue.front();
|
||||
}
|
||||
}
|
||||
|
||||
if (frame.FrameNum > NDS::NumFrames)
|
||||
{
|
||||
// frame in the future, ignore
|
||||
return;
|
||||
}
|
||||
|
||||
// apply this input frame
|
||||
printf("[%08d] INPUT=%08X (%08d) (backlog=%d)\n", NDS::NumFrames, frame.KeyMask, frame.FrameNum, InputQueue.size());
|
||||
NDS::SetKeyMask(frame.KeyMask);
|
||||
InputQueue.pop();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -32,7 +32,10 @@ void DeInit();
|
||||
void StartHost();
|
||||
void StartClient();
|
||||
|
||||
void StartGame();
|
||||
|
||||
void ProcessFrame();
|
||||
void ProcessInput();
|
||||
|
||||
}
|
||||
|
||||
|
@ -472,7 +472,14 @@ void EmuThread::run()
|
||||
}
|
||||
|
||||
// process input and hotkeys
|
||||
NDS::SetKeyMask(Input::InputMask);
|
||||
if (Netplay::Active)
|
||||
{
|
||||
Netplay::ProcessInput();
|
||||
}
|
||||
else
|
||||
{
|
||||
NDS::SetKeyMask(Input::InputMask);
|
||||
}
|
||||
|
||||
if (Input::HotkeyPressed(HK_Lid))
|
||||
{
|
||||
@ -1576,6 +1583,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
|
||||
|
||||
actMPStartClient = submenu->addAction("NETPLAY CLIENT");
|
||||
connect(actMPStartClient, &QAction::triggered, this, &MainWindow::onMPStartClient);
|
||||
|
||||
actMPTest = submenu->addAction("NETPLAY GO");
|
||||
connect(actMPTest, &QAction::triggered, this, &MainWindow::onMPTest);
|
||||
}
|
||||
}
|
||||
{
|
||||
@ -2337,8 +2347,11 @@ void MainWindow::onOpenFile()
|
||||
recentFileList.prepend(filename);
|
||||
updateRecentFilesMenu();
|
||||
|
||||
NDS::Start();
|
||||
emuThread->emuRun();
|
||||
if (!Netplay::Active)
|
||||
{
|
||||
NDS::Start();
|
||||
emuThread->emuRun();
|
||||
}
|
||||
|
||||
updateCartInserted(false);
|
||||
}
|
||||
@ -2434,8 +2447,11 @@ void MainWindow::onClickRecentFile()
|
||||
recentFileList.prepend(filename);
|
||||
updateRecentFilesMenu();
|
||||
|
||||
NDS::Start();
|
||||
emuThread->emuRun();
|
||||
if (!Netplay::Active)
|
||||
{
|
||||
NDS::Start();
|
||||
emuThread->emuRun();
|
||||
}
|
||||
|
||||
updateCartInserted(false);
|
||||
}
|
||||
@ -2458,8 +2474,11 @@ void MainWindow::onBootFirmware()
|
||||
return;
|
||||
}
|
||||
|
||||
NDS::Start();
|
||||
emuThread->emuRun();
|
||||
if (!Netplay::Active)
|
||||
{
|
||||
NDS::Start();
|
||||
emuThread->emuRun();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onInsertCart()
|
||||
@ -2844,6 +2863,12 @@ void MainWindow::onMPStartClient()
|
||||
Netplay::StartClient();
|
||||
}
|
||||
|
||||
void MainWindow::onMPTest()
|
||||
{
|
||||
// HAX
|
||||
Netplay::StartGame();
|
||||
}
|
||||
|
||||
void MainWindow::onOpenEmuSettings()
|
||||
{
|
||||
emuThread->emuPause();
|
||||
|
@ -313,6 +313,7 @@ private slots:
|
||||
void onMPNewInstance();
|
||||
void onMPStartHost();
|
||||
void onMPStartClient();
|
||||
void onMPTest();
|
||||
|
||||
void onOpenEmuSettings();
|
||||
void onEmuSettingsDialogFinished(int res);
|
||||
@ -412,6 +413,7 @@ public:
|
||||
QAction* actMPNewInstance;
|
||||
QAction* actMPStartHost;
|
||||
QAction* actMPStartClient;
|
||||
QAction* actMPTest;
|
||||
|
||||
QAction* actEmuSettings;
|
||||
#ifdef __APPLE__
|
||||
|
Loading…
Reference in New Issue
Block a user