mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-14 00:54:05 +02:00
#142 network multiplayer basic protocol and routine (WIP)
This commit is contained in:
10
src/core.h
10
src/core.h
@@ -15,6 +15,7 @@
|
|||||||
#define _GAPI_GL 1
|
#define _GAPI_GL 1
|
||||||
//#define _GAPI_D3D9 1
|
//#define _GAPI_D3D9 1
|
||||||
//#define _GAPI_VULKAN 1
|
//#define _GAPI_VULKAN 1
|
||||||
|
//#define _NAPI_SOCKET
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
@@ -324,6 +325,12 @@ namespace Core {
|
|||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
|
|
||||||
|
#if defined(_NAPI_SOCKET)
|
||||||
|
#include "napi_socket.h"
|
||||||
|
#else
|
||||||
|
#include "napi_dummy.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MAX_LIGHTS 4
|
#define MAX_LIGHTS 4
|
||||||
#define MAX_RENDER_BUFFERS 32
|
#define MAX_RENDER_BUFFERS 32
|
||||||
#define MAX_CONTACTS 15
|
#define MAX_CONTACTS 15
|
||||||
@@ -622,6 +629,7 @@ namespace Core {
|
|||||||
|
|
||||||
Input::init();
|
Input::init();
|
||||||
Sound::init();
|
Sound::init();
|
||||||
|
NAPI::init();
|
||||||
|
|
||||||
GAPI::init();
|
GAPI::init();
|
||||||
|
|
||||||
@@ -770,7 +778,7 @@ namespace Core {
|
|||||||
delete ditherTex;
|
delete ditherTex;
|
||||||
|
|
||||||
GAPI::deinit();
|
GAPI::deinit();
|
||||||
|
NAPI::deinit();
|
||||||
Sound::deinit();
|
Sound::deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -173,6 +173,7 @@ namespace Game {
|
|||||||
|
|
||||||
void updateTick() {
|
void updateTick() {
|
||||||
Input::update();
|
Input::update();
|
||||||
|
Network::update();
|
||||||
|
|
||||||
cheatControl(Input::lastState[0]);
|
cheatControl(Input::lastState[0]);
|
||||||
|
|
||||||
|
11
src/lara.h
11
src/lara.h
@@ -320,6 +320,8 @@ struct Lara : Character {
|
|||||||
|
|
||||||
float hitTimer;
|
float hitTimer;
|
||||||
|
|
||||||
|
int32 networkInput;
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
//uint16 *dbgBoxes;
|
//uint16 *dbgBoxes;
|
||||||
//int dbgBoxesCount;
|
//int dbgBoxesCount;
|
||||||
@@ -494,8 +496,9 @@ struct Lara : Character {
|
|||||||
Lara(IGame *game, int entity) : Character(game, entity, LARA_MAX_HEALTH), dozy(false), wpnCurrent(TR::Entity::NONE), wpnNext(TR::Entity::NONE), braid(NULL) {
|
Lara(IGame *game, int entity) : Character(game, entity, LARA_MAX_HEALTH), dozy(false), wpnCurrent(TR::Entity::NONE), wpnNext(TR::Entity::NONE), braid(NULL) {
|
||||||
camera = new Camera(game, this);
|
camera = new Camera(game, this);
|
||||||
|
|
||||||
itemHolster = TR::Entity::NONE;
|
itemHolster = TR::Entity::NONE;
|
||||||
hitTimer = 0.0f;
|
hitTimer = 0.0f;
|
||||||
|
networkInput = -1;
|
||||||
|
|
||||||
if (level->extra.laraSkin > -1)
|
if (level->extra.laraSkin > -1)
|
||||||
level->entities[entity].modelIndex = level->extra.laraSkin + 1;
|
level->entities[entity].modelIndex = level->extra.laraSkin + 1;
|
||||||
@@ -2893,6 +2896,10 @@ struct Lara : Character {
|
|||||||
|
|
||||||
virtual int getInput() { // TODO: updateInput
|
virtual int getInput() { // TODO: updateInput
|
||||||
if (level->isCutsceneLevel()) return 0;
|
if (level->isCutsceneLevel()) return 0;
|
||||||
|
|
||||||
|
if (networkInput != -1)
|
||||||
|
return networkInput;
|
||||||
|
|
||||||
input = 0;
|
input = 0;
|
||||||
int pid = camera->cameraIndex;
|
int pid = camera->cameraIndex;
|
||||||
|
|
||||||
|
12
src/level.h
12
src/level.h
@@ -11,6 +11,7 @@
|
|||||||
#include "trigger.h"
|
#include "trigger.h"
|
||||||
#include "inventory.h"
|
#include "inventory.h"
|
||||||
#include "savegame.h"
|
#include "savegame.h"
|
||||||
|
#include "network.h"
|
||||||
|
|
||||||
#if defined(_DEBUG) && defined(_GAPI_GL) && !defined(_GAPI_GLES)
|
#if defined(_DEBUG) && defined(_GAPI_GL) && !defined(_GAPI_GLES)
|
||||||
#define DEBUG_RENDER
|
#define DEBUG_RENDER
|
||||||
@@ -872,10 +873,14 @@ struct Level : IGame {
|
|||||||
loadSlot = -1;
|
loadSlot = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Network::start(this);
|
||||||
|
|
||||||
Core::resetTime();
|
Core::resetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Level() {
|
virtual ~Level() {
|
||||||
|
Network::stop();
|
||||||
|
|
||||||
for (int i = 0; i < level.entitiesCount; i++)
|
for (int i = 0; i < level.entitiesCount; i++)
|
||||||
delete (Controller*)level.entities[i].controller;
|
delete (Controller*)level.entities[i].controller;
|
||||||
|
|
||||||
@@ -1812,6 +1817,13 @@ struct Level : IGame {
|
|||||||
sndWater->setVolume(volWater, 0.2f);
|
sndWater->setVolume(volWater, 0.2f);
|
||||||
if (sndTrack && sndTrack->volumeTarget != volTrack)
|
if (sndTrack && sndTrack->volumeTarget != volTrack)
|
||||||
sndTrack->setVolume(volTrack, 0.2f);
|
sndTrack->setVolume(volTrack, 0.2f);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
if (Input::down[ikJ]) {
|
||||||
|
Network::sayHello();
|
||||||
|
Input::down[ikJ] = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateEffect() {
|
void updateEffect() {
|
||||||
|
17
src/napi_dummy.h
Normal file
17
src/napi_dummy.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef H_NAPI_DUMMY
|
||||||
|
#define H_NAPI_DUMMYT
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
namespace NAPI {
|
||||||
|
typedef int Peer;
|
||||||
|
|
||||||
|
void init() {}
|
||||||
|
void deinit() {}
|
||||||
|
void listen(uint16 port) {}
|
||||||
|
int send(const Peer &to, const void *data, int size) { return 0; }
|
||||||
|
int recv(Peer &from, void *data, int size) { return 0; }
|
||||||
|
void broadcast(const void *data, int size) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
103
src/napi_socket.h
Normal file
103
src/napi_socket.h
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
#ifndef H_NAPI_SOCKET
|
||||||
|
#define H_NAPI_SOCKET
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#ifdef _OS_WIN
|
||||||
|
#include "winsock.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace NAPI {
|
||||||
|
|
||||||
|
struct Peer {
|
||||||
|
uint16 port;
|
||||||
|
uint32 ip;
|
||||||
|
|
||||||
|
inline bool operator == (const Peer &peer) const {
|
||||||
|
return port == peer.port && ip == peer.ip;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SOCKET sock;
|
||||||
|
sockaddr_in addr;
|
||||||
|
uint16 port;
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
sock = INVALID_SOCKET;
|
||||||
|
|
||||||
|
WSAData wData;
|
||||||
|
WSAStartup(0x0101, &wData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deinit() {
|
||||||
|
if (sock != INVALID_SOCKET) {
|
||||||
|
shutdown(sock, 1);
|
||||||
|
#ifdef _OS_WIN
|
||||||
|
closesocket(sock);
|
||||||
|
#else
|
||||||
|
close(sock);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
WSACleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void listen(uint16 port) {
|
||||||
|
NAPI::port = port;
|
||||||
|
|
||||||
|
if (sock != INVALID_SOCKET) return;
|
||||||
|
|
||||||
|
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (sock == INVALID_SOCKET) {
|
||||||
|
LOG("! network: failed to create socket\n");
|
||||||
|
sock = INVALID_SOCKET;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u_long on = 1;
|
||||||
|
if (ioctlsocket(sock, FIONBIO, &on) < 0) {
|
||||||
|
LOG("! network: failed to set non-blocking mode\n");
|
||||||
|
closesocket(sock);
|
||||||
|
sock = INVALID_SOCKET;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(port);
|
||||||
|
if (bind(sock, (sockaddr*)&addr, sizeof(addr)))
|
||||||
|
LOG("! network: unable to bind socket on port (%d)\n", (int)port);
|
||||||
|
|
||||||
|
on = 1;
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&on, sizeof(on)))
|
||||||
|
LOG("! network: unable to enable broadcasting\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int send(const Peer &to, const void *data, int size) {
|
||||||
|
if (sock == INVALID_SOCKET) return false;
|
||||||
|
|
||||||
|
addr.sin_addr.s_addr = to.ip;
|
||||||
|
addr.sin_port = to.port;
|
||||||
|
return sendto(sock, (const char*)data, size, 0, (sockaddr*)&addr, sizeof(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
int recv(Peer &from, void *data, int size) {
|
||||||
|
if (sock == INVALID_SOCKET) return false;
|
||||||
|
|
||||||
|
int i = sizeof(addr);
|
||||||
|
int count = recvfrom(sock, (char*)data, size, 0, (sockaddr*)&addr, &i);
|
||||||
|
if (count > 0) {
|
||||||
|
from.ip = addr.sin_addr.s_addr;
|
||||||
|
from.port = addr.sin_port;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void broadcast(const void *data, int size) {
|
||||||
|
Peer peer;
|
||||||
|
peer.ip = INADDR_BROADCAST;
|
||||||
|
peer.port = htons(port);
|
||||||
|
send(peer, data, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
354
src/network.h
Normal file
354
src/network.h
Normal file
@@ -0,0 +1,354 @@
|
|||||||
|
#ifndef H_NET
|
||||||
|
#define H_NET
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "format.h"
|
||||||
|
#include "controller.h"
|
||||||
|
#include "ui.h"
|
||||||
|
|
||||||
|
#define NET_PROTOCOL 1
|
||||||
|
#define NET_PORT 21468
|
||||||
|
|
||||||
|
#define NET_PING_TIMEOUT ( 1000 * 10 )
|
||||||
|
#define NET_PING_PERIOD ( 1000 * 3 )
|
||||||
|
#define NET_SYMC_INPUT_PERIOD ( 1000 / 25 )
|
||||||
|
#define NET_SYMC_STATE_PERIOD ( 1000 / 1000 )
|
||||||
|
|
||||||
|
namespace Network {
|
||||||
|
|
||||||
|
struct Packet {
|
||||||
|
enum Type {
|
||||||
|
HELLO, INFO, PING, PONG, JOIN, ACCEPT, REJECT, INPUT, STATE,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint16 type;
|
||||||
|
uint16 id;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint8 protocol;
|
||||||
|
uint8 game;
|
||||||
|
} hello;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
str16 name;
|
||||||
|
uint8 level;
|
||||||
|
uint8 players;
|
||||||
|
struct {
|
||||||
|
uint16 secure:1;
|
||||||
|
} flags;
|
||||||
|
} info;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
str16 nick;
|
||||||
|
str16 pass;
|
||||||
|
} join;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint16 id;
|
||||||
|
uint8 level;
|
||||||
|
uint8 roomIndex;
|
||||||
|
int16 posX;
|
||||||
|
int16 posY;
|
||||||
|
int16 posZ;
|
||||||
|
int16 angle;
|
||||||
|
} accept;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint16 reason;
|
||||||
|
} reject;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint16 mask;
|
||||||
|
} input;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint8 roomIndex;
|
||||||
|
uint8 reserved;
|
||||||
|
int16 pos[3];
|
||||||
|
int16 angle[2];
|
||||||
|
uint8 frame;
|
||||||
|
uint8 stand;
|
||||||
|
uint16 animIndex;
|
||||||
|
} state;
|
||||||
|
};
|
||||||
|
|
||||||
|
int getSize() const {
|
||||||
|
const int sizes[] = {
|
||||||
|
sizeof(hello),
|
||||||
|
sizeof(info),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
sizeof(join),
|
||||||
|
sizeof(accept),
|
||||||
|
sizeof(reject),
|
||||||
|
sizeof(input),
|
||||||
|
sizeof(state),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (type >= 0 && type < COUNT(sizes))
|
||||||
|
return 2 + 2 + sizes[type];
|
||||||
|
ASSERT(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
IGame *game;
|
||||||
|
|
||||||
|
struct Player {
|
||||||
|
NAPI::Peer peer;
|
||||||
|
int pingTime;
|
||||||
|
int pingIndex;
|
||||||
|
Controller *controller;
|
||||||
|
};
|
||||||
|
|
||||||
|
Array<Player> players;
|
||||||
|
|
||||||
|
int syncInputTime;
|
||||||
|
int syncStateTime;
|
||||||
|
|
||||||
|
void start(IGame *game) {
|
||||||
|
Network::game = game;
|
||||||
|
NAPI::listen(NET_PORT);
|
||||||
|
syncInputTime = syncStateTime = osGetTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop() {
|
||||||
|
players.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sendPacket(const NAPI::Peer &to, const Packet &packet) {
|
||||||
|
return NAPI::send(to, &packet, packet.getSize()) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool recvPacket(NAPI::Peer &from, Packet &packet) {
|
||||||
|
int count = NAPI::recv(from, &packet, sizeof(packet));
|
||||||
|
if (count > 0) {
|
||||||
|
if (count != packet.getSize()) {
|
||||||
|
ASSERT(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sayHello() {
|
||||||
|
Packet packet;
|
||||||
|
packet.type = Packet::HELLO;
|
||||||
|
packet.hello.protocol = NET_PROTOCOL;
|
||||||
|
packet.hello.game = game->getLevel()->version & TR::VER_VERSION;
|
||||||
|
|
||||||
|
NAPI::broadcast(&packet, packet.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
void joinGame(const NAPI::Peer &peer) {
|
||||||
|
Packet packet;
|
||||||
|
packet.type = Packet::JOIN;
|
||||||
|
packet.join.nick = "Player_2";
|
||||||
|
packet.join.pass = "";
|
||||||
|
LOG("join game\n");
|
||||||
|
sendPacket(peer, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pingPlayers(int time) {
|
||||||
|
int i = 0;
|
||||||
|
while (i < players.length) {
|
||||||
|
int delta = time - players[i].pingTime;
|
||||||
|
|
||||||
|
if (delta > NET_PING_TIMEOUT) {
|
||||||
|
players.removeFast(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delta > NET_PING_PERIOD) {
|
||||||
|
Packet packet;
|
||||||
|
packet.type = Packet::PING;
|
||||||
|
sendPacket(players[i].peer, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void syncInput(int time) {
|
||||||
|
Lara *lara = (Lara*)game->getLara();
|
||||||
|
if (!lara) return;
|
||||||
|
|
||||||
|
if ((time - syncInputTime) < NET_SYMC_INPUT_PERIOD)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Packet packet;
|
||||||
|
packet.type = Packet::INPUT;
|
||||||
|
packet.input.mask = lara->getInput();
|
||||||
|
|
||||||
|
for (int i = 0; i < players.length; i++)
|
||||||
|
sendPacket(players[i].peer, packet);
|
||||||
|
|
||||||
|
syncInputTime = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
void syncState(int time) {
|
||||||
|
if ((time - syncStateTime) < NET_SYMC_STATE_PERIOD)
|
||||||
|
return;
|
||||||
|
// TODO
|
||||||
|
syncStateTime = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player* getPlayerByPeer(const NAPI::Peer &peer) {
|
||||||
|
for (int i = 0; i < players.length; i++)
|
||||||
|
if (players[i].peer == peer) {
|
||||||
|
return &players[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void getSpawnPoint(uint8 &roomIndex, vec3 &pos, float &angle) {
|
||||||
|
Controller *lara = game->getLara();
|
||||||
|
roomIndex = lara->getRoomIndex();
|
||||||
|
pos = lara->getPos();
|
||||||
|
angle = normalizeAngle(lara->angle.y); // 0..2PI
|
||||||
|
}
|
||||||
|
|
||||||
|
void update() {
|
||||||
|
int count;
|
||||||
|
NAPI::Peer from;
|
||||||
|
Packet packet, response;
|
||||||
|
|
||||||
|
int time = osGetTime();
|
||||||
|
|
||||||
|
while ( (count = recvPacket(from, packet)) > 0 ) {
|
||||||
|
Player *player = getPlayerByPeer(from);
|
||||||
|
if (player)
|
||||||
|
player->pingTime = time;
|
||||||
|
|
||||||
|
switch (packet.type) {
|
||||||
|
case Packet::HELLO :
|
||||||
|
if (game->getLevel()->isTitle())
|
||||||
|
break;
|
||||||
|
|
||||||
|
LOG("recv HELLO\n");
|
||||||
|
if (packet.hello.game != (game->getLevel()->version & TR::VER_VERSION))
|
||||||
|
break;
|
||||||
|
if (packet.hello.protocol != NET_PROTOCOL)
|
||||||
|
break;
|
||||||
|
LOG("send INFO\n");
|
||||||
|
response.type = Packet::INFO;
|
||||||
|
response.info.name = "MultiOpenLara";
|
||||||
|
response.info.level = game->getLevel()->id;
|
||||||
|
response.info.players = players.length + 1;
|
||||||
|
response.info.flags.secure = false;
|
||||||
|
|
||||||
|
sendPacket(from, response);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Packet::INFO : {
|
||||||
|
LOG("recv INFO\n");
|
||||||
|
char buf[sizeof(packet.info.name) + 1];
|
||||||
|
packet.info.name.get(buf);
|
||||||
|
LOG("name: %s\n", buf);
|
||||||
|
joinGame(from);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Packet::PING :
|
||||||
|
if (player) {
|
||||||
|
response.type = Packet::PONG;
|
||||||
|
sendPacket(from, response);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Packet::PONG :
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Packet::JOIN :
|
||||||
|
if (!player) {
|
||||||
|
uint8 roomIndex;
|
||||||
|
vec3 pos;
|
||||||
|
float angle;
|
||||||
|
|
||||||
|
getSpawnPoint(roomIndex, pos, angle);
|
||||||
|
|
||||||
|
Player newPlayer;
|
||||||
|
newPlayer.peer = from;
|
||||||
|
newPlayer.pingIndex = 0;
|
||||||
|
newPlayer.pingTime = time;
|
||||||
|
newPlayer.controller = game->addEntity(TR::Entity::LARA, roomIndex, pos, angle);
|
||||||
|
players.push(newPlayer);
|
||||||
|
|
||||||
|
((Lara*)newPlayer.controller)->networkInput = 0;
|
||||||
|
|
||||||
|
char buf[32];
|
||||||
|
packet.join.nick.get(buf);
|
||||||
|
LOG("Player %s joined\n", buf);
|
||||||
|
|
||||||
|
ASSERT(newPlayer.controller);
|
||||||
|
|
||||||
|
TR::Room &room = game->getLevel()->rooms[roomIndex];
|
||||||
|
vec3 offset = pos - room.getOffset();
|
||||||
|
|
||||||
|
response.type = Packet::ACCEPT;
|
||||||
|
response.accept.id = 0;
|
||||||
|
response.accept.level = game->getLevel()->id;
|
||||||
|
response.accept.roomIndex = roomIndex;
|
||||||
|
response.accept.posX = int16(offset.x);
|
||||||
|
response.accept.posY = int16(offset.y);
|
||||||
|
response.accept.posZ = int16(offset.z);
|
||||||
|
response.accept.angle = int16(angle * RAD2DEG);
|
||||||
|
|
||||||
|
sendPacket(from, response);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Packet::ACCEPT : {
|
||||||
|
LOG("accept!\n");
|
||||||
|
game->loadLevel(TR::LevelID(packet.accept.level));
|
||||||
|
inventory->toggle();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Packet::REJECT :
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Packet::INPUT :
|
||||||
|
if (game->getLevel()->isTitle())
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!player) {
|
||||||
|
uint8 roomIndex;
|
||||||
|
vec3 pos;
|
||||||
|
float angle;
|
||||||
|
|
||||||
|
getSpawnPoint(roomIndex, pos, angle);
|
||||||
|
|
||||||
|
Player newPlayer;
|
||||||
|
newPlayer.peer = from;
|
||||||
|
newPlayer.pingIndex = 0;
|
||||||
|
newPlayer.pingTime = time;
|
||||||
|
newPlayer.controller = game->addEntity(TR::Entity::LARA, roomIndex, pos, angle);
|
||||||
|
players.push(newPlayer);
|
||||||
|
|
||||||
|
((Lara*)newPlayer.controller)->networkInput = 0;
|
||||||
|
|
||||||
|
player = getPlayerByPeer(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player) {
|
||||||
|
((Lara*)player->controller)->networkInput = packet.input.mask;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Packet::STATE :
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pingPlayers(time);
|
||||||
|
syncInput(time);
|
||||||
|
syncState(time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@@ -106,7 +106,7 @@
|
|||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>openvr_api.lib;d3d9.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>wsock32.lib;openvr_api.lib;d3d9.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Editor|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Editor|Win32'">
|
||||||
@@ -149,7 +149,7 @@
|
|||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>wcrt.lib;openvr_api.lib;d3d9.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>wcrt.lib;wsock32.lib;openvr_api.lib;d3d9.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
@@ -179,7 +179,7 @@
|
|||||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>wcrt.lib;openvr_api.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>wcrt.lib;wsock32.lib;openvr_api.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||||
@@ -199,6 +199,7 @@
|
|||||||
<ClInclude Include="..\..\collision.h" />
|
<ClInclude Include="..\..\collision.h" />
|
||||||
<ClInclude Include="..\..\controller.h" />
|
<ClInclude Include="..\..\controller.h" />
|
||||||
<ClInclude Include="..\..\core.h" />
|
<ClInclude Include="..\..\core.h" />
|
||||||
|
<ClInclude Include="..\..\format.h" />
|
||||||
<ClInclude Include="..\..\gapi_d3d9.h" />
|
<ClInclude Include="..\..\gapi_d3d9.h" />
|
||||||
<ClInclude Include="..\..\gapi_gl.h" />
|
<ClInclude Include="..\..\gapi_gl.h" />
|
||||||
<ClInclude Include="..\..\gapi_gu.h" />
|
<ClInclude Include="..\..\gapi_gu.h" />
|
||||||
@@ -209,12 +210,14 @@
|
|||||||
<ClInclude Include="..\..\frustum.h" />
|
<ClInclude Include="..\..\frustum.h" />
|
||||||
<ClInclude Include="..\..\game.h" />
|
<ClInclude Include="..\..\game.h" />
|
||||||
<ClInclude Include="..\..\gameflow.h" />
|
<ClInclude Include="..\..\gameflow.h" />
|
||||||
<ClInclude Include="..\..\libs\tinf\tinf.h" />
|
<ClInclude Include="..\..\napi_dummy.h" />
|
||||||
<ClInclude Include="..\..\ui.h" />
|
<ClInclude Include="..\..\napi_socket.h" />
|
||||||
|
<ClInclude Include="..\..\network.h" />
|
||||||
<ClInclude Include="..\..\input.h" />
|
<ClInclude Include="..\..\input.h" />
|
||||||
<ClInclude Include="..\..\inventory.h" />
|
<ClInclude Include="..\..\inventory.h" />
|
||||||
<ClInclude Include="..\..\lara.h" />
|
<ClInclude Include="..\..\lara.h" />
|
||||||
<ClInclude Include="..\..\level.h" />
|
<ClInclude Include="..\..\level.h" />
|
||||||
|
<ClInclude Include="..\..\libs\tinf\tinf.h" />
|
||||||
<ClInclude Include="..\..\libs\minimp3\libc.h" />
|
<ClInclude Include="..\..\libs\minimp3\libc.h" />
|
||||||
<ClInclude Include="..\..\libs\minimp3\minimp3.h" />
|
<ClInclude Include="..\..\libs\minimp3\minimp3.h" />
|
||||||
<ClInclude Include="..\..\mesh.h" />
|
<ClInclude Include="..\..\mesh.h" />
|
||||||
@@ -223,9 +226,9 @@
|
|||||||
<ClInclude Include="..\..\sound.h" />
|
<ClInclude Include="..\..\sound.h" />
|
||||||
<ClInclude Include="..\..\sprite.h" />
|
<ClInclude Include="..\..\sprite.h" />
|
||||||
<ClInclude Include="..\..\texture.h" />
|
<ClInclude Include="..\..\texture.h" />
|
||||||
<ClInclude Include="..\..\format.h" />
|
|
||||||
<ClInclude Include="..\..\trigger.h" />
|
<ClInclude Include="..\..\trigger.h" />
|
||||||
<ClInclude Include="..\..\utils.h" />
|
<ClInclude Include="..\..\utils.h" />
|
||||||
|
<ClInclude Include="..\..\ui.h" />
|
||||||
<ClInclude Include="..\..\video.h" />
|
<ClInclude Include="..\..\video.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@@ -54,6 +54,9 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\video.h" />
|
<ClInclude Include="..\..\video.h" />
|
||||||
<ClInclude Include="..\..\savegame.h" />
|
<ClInclude Include="..\..\savegame.h" />
|
||||||
|
<ClInclude Include="..\..\network.h" />
|
||||||
|
<ClInclude Include="..\..\napi_socket.h" />
|
||||||
|
<ClInclude Include="..\..\napi_dummy.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\shaders\filter.glsl">
|
<None Include="..\..\shaders\filter.glsl">
|
||||||
|
24
src/utils.h
24
src/utils.h
@@ -1638,6 +1638,27 @@ namespace String {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <int N>
|
||||||
|
struct FixedStr {
|
||||||
|
char data[N];
|
||||||
|
|
||||||
|
void get(char *dst) {
|
||||||
|
memcpy(dst, data, sizeof(data));
|
||||||
|
dst[sizeof(data)] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedStr<N>& operator = (const char *str) {
|
||||||
|
int len = min(sizeof(data), strlen(str));
|
||||||
|
memset(data, 0, sizeof(data));
|
||||||
|
memcpy(data, str, len);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef FixedStr<16> str16;
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Array {
|
struct Array {
|
||||||
int capacity;
|
int capacity;
|
||||||
@@ -1675,7 +1696,8 @@ struct Array {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void removeFast(int index) {
|
void removeFast(int index) {
|
||||||
(*this)[index] = (*this)[--length];
|
(*this)[index] = (*this)[length - 1];
|
||||||
|
length--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(int index) {
|
void remove(int index) {
|
||||||
|
Reference in New Issue
Block a user