mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-27 13:39:42 +00:00
Merge branch '0.7.0' of https://github.com/TES3MP/openmw-tes3mp into 0.7.0
This commit is contained in:
commit
6c50d4199b
5 changed files with 101 additions and 84 deletions
|
@ -1,6 +1,9 @@
|
||||||
TES3MP
|
TES3MP
|
||||||
======
|
======
|
||||||
|
|
||||||
|
Copyright (c) 2008-2015, OpenMW Team
|
||||||
|
Copyright (c) 2016-2018, TES3MP Team
|
||||||
|
|
||||||
[](https://travis-ci.org/TES3MP/openmw-tes3mp)
|
[](https://travis-ci.org/TES3MP/openmw-tes3mp)
|
||||||
|
|
||||||
TES3MP is a project aiming to add multiplayer functionality to [OpenMW](https://github.com/OpenMW/openmw), an open-source game engine that supports playing "The Elder Scrolls III: Morrowind" by Bethesda Softworks.
|
TES3MP is a project aiming to add multiplayer functionality to [OpenMW](https://github.com/OpenMW/openmw), an open-source game engine that supports playing "The Elder Scrolls III: Morrowind" by Bethesda Softworks.
|
||||||
|
|
|
@ -212,88 +212,84 @@ void Networking::processWorldstatePacket(RakNet::Packet *packet)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Networking::update(RakNet::Packet *packet)
|
bool Networking::preInit(RakNet::Packet *packet, RakNet::BitStream &bsIn)
|
||||||
{
|
{
|
||||||
Player *player = Players::getPlayer(packet->guid);
|
if (packet->data[0] != ID_GAME_PREINIT)
|
||||||
|
|
||||||
RakNet::BitStream bsIn(&packet->data[1], packet->length, false);
|
|
||||||
|
|
||||||
bsIn.IgnoreBytes((unsigned int) RakNet::RakNetGUID::size()); // Ignore GUID from received packet
|
|
||||||
|
|
||||||
if (player == nullptr)
|
|
||||||
{
|
{
|
||||||
if (packet->data[0] == ID_GAME_PREINIT)
|
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "%s sent wrong first packet (ID_GAME_PREINIT was expected)",
|
||||||
{
|
packet->systemAddress.ToString());
|
||||||
DEBUG_PRINTF("ID_GAME_PREINIT");
|
peer->CloseConnection(packet->systemAddress, true);
|
||||||
PacketPreInit::PluginContainer plugins;
|
|
||||||
|
|
||||||
PacketPreInit packetPreInit(peer);
|
|
||||||
packetPreInit.SetReadStream(&bsIn);
|
|
||||||
packetPreInit.setChecksums(&plugins);
|
|
||||||
packetPreInit.Read();
|
|
||||||
|
|
||||||
if (!packetPreInit.isPacketValid())
|
|
||||||
{
|
|
||||||
LOG_APPEND(Log::LOG_ERROR, "Invalid packetPreInit");
|
|
||||||
peer->CloseConnection(packet->systemAddress, false); // close connection without notification
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto plugin = plugins.begin();
|
|
||||||
if (samples.size() == plugins.size())
|
|
||||||
{
|
|
||||||
for (int i = 0; plugin != plugins.end(); plugin++, i++)
|
|
||||||
{
|
|
||||||
LOG_APPEND(Log::LOG_VERBOSE, "- %X\t%s", plugin->second[0], plugin->first.c_str());
|
|
||||||
// Check if the filenames match, ignoring case
|
|
||||||
if (Misc::StringUtils::ciEqual(samples[i].first, plugin->first))
|
|
||||||
{
|
|
||||||
auto &hashList = samples[i].second;
|
|
||||||
// Proceed if no checksums have been listed for this plugin on the server
|
|
||||||
if (hashList.empty())
|
|
||||||
continue;
|
|
||||||
auto it = find(hashList.begin(), hashList.end(), plugin->second[0]);
|
|
||||||
// Break the loop if the client's checksum isn't among those accepted by
|
|
||||||
// the server
|
|
||||||
if (it == hashList.end())
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
else // name is incorrect
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RakNet::BitStream bs;
|
|
||||||
packetPreInit.SetSendStream(&bs);
|
|
||||||
|
|
||||||
// If the loop above was broken, then the client's plugins do not match the server's
|
|
||||||
if (pluginEnforcementState && plugin != plugins.end())
|
|
||||||
{
|
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "%s was not allowed to connect due to incompatible plugins", packet->systemAddress.ToString());
|
|
||||||
packetPreInit.setChecksums(&samples);
|
|
||||||
packetPreInit.Send(packet->systemAddress);
|
|
||||||
peer->CloseConnection(packet->systemAddress, true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "%s was allowed to connect", packet->systemAddress.ToString());
|
|
||||||
PacketPreInit::PluginContainer tmp;
|
|
||||||
packetPreInit.setChecksums(&tmp);
|
|
||||||
packetPreInit.Send(packet->systemAddress);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
playerPacketController->SetStream(&bsIn, 0);
|
|
||||||
|
|
||||||
playerPacketController->GetPacket(ID_HANDSHAKE)->RequestData(packet->guid);
|
|
||||||
Players::newPlayer(packet->guid);
|
|
||||||
player = Players::getPlayer(packet->guid);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else if (playerPacketController->ContainsPacket(packet->data[0]))
|
|
||||||
|
DEBUG_PRINTF("ID_GAME_PREINIT");
|
||||||
|
PacketPreInit::PluginContainer plugins;
|
||||||
|
|
||||||
|
PacketPreInit packetPreInit(peer);
|
||||||
|
packetPreInit.SetReadStream(&bsIn);
|
||||||
|
packetPreInit.setChecksums(&plugins);
|
||||||
|
packetPreInit.Read();
|
||||||
|
|
||||||
|
if (!packetPreInit.isPacketValid() || plugins.empty())
|
||||||
{
|
{
|
||||||
playerPacketController->SetStream(&bsIn, 0);
|
LOG_APPEND(Log::LOG_ERROR, "Invalid packetPreInit");
|
||||||
|
peer->CloseConnection(packet->systemAddress, false); // close connection without notification
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto plugin = plugins.begin();
|
||||||
|
if (samples.size() == plugins.size())
|
||||||
|
{
|
||||||
|
for (int i = 0; plugin != plugins.end(); plugin++, i++)
|
||||||
|
{
|
||||||
|
LOG_APPEND(Log::LOG_VERBOSE, "- %X\t%s", plugin->second[0], plugin->first.c_str());
|
||||||
|
// Check if the filenames match, ignoring case
|
||||||
|
if (Misc::StringUtils::ciEqual(samples[i].first, plugin->first))
|
||||||
|
{
|
||||||
|
auto &hashList = samples[i].second;
|
||||||
|
// Proceed if no checksums have been listed for this plugin on the server
|
||||||
|
if (hashList.empty())
|
||||||
|
continue;
|
||||||
|
auto it = find(hashList.begin(), hashList.end(), plugin->second[0]);
|
||||||
|
// Break the loop if the client's checksum isn't among those accepted by
|
||||||
|
// the server
|
||||||
|
if (it == hashList.end())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else // name is incorrect
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RakNet::BitStream bs;
|
||||||
|
packetPreInit.SetSendStream(&bs);
|
||||||
|
|
||||||
|
// If the loop above was broken, then the client's plugins do not match the server's
|
||||||
|
if (pluginEnforcementState && plugin != plugins.end())
|
||||||
|
{
|
||||||
|
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "%s was not allowed to connect due to incompatible plugins", packet->systemAddress.ToString());
|
||||||
|
packetPreInit.setChecksums(&samples);
|
||||||
|
packetPreInit.Send(packet->systemAddress);
|
||||||
|
peer->CloseConnection(packet->systemAddress, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "%s was allowed to connect", packet->systemAddress.ToString());
|
||||||
|
PacketPreInit::PluginContainer tmp;
|
||||||
|
packetPreInit.setChecksums(&tmp);
|
||||||
|
packetPreInit.Send(packet->systemAddress);
|
||||||
|
Players::newPlayer(packet->guid); // create player if connection allowed
|
||||||
|
playerPacketController->SetStream(&bsIn, nullptr); // and request handshake
|
||||||
|
playerPacketController->GetPacket(ID_HANDSHAKE)->RequestData(packet->guid);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Networking::update(RakNet::Packet *packet, RakNet::BitStream &bsIn)
|
||||||
|
{
|
||||||
|
if (playerPacketController->ContainsPacket(packet->data[0]))
|
||||||
|
{
|
||||||
|
playerPacketController->SetStream(&bsIn, nullptr);
|
||||||
processPlayerPacket(packet);
|
processPlayerPacket(packet);
|
||||||
}
|
}
|
||||||
else if (actorPacketController->ContainsPacket(packet->data[0]))
|
else if (actorPacketController->ContainsPacket(packet->data[0]))
|
||||||
|
@ -531,8 +527,17 @@ int Networking::mainLoop()
|
||||||
case ID_UNCONNECTED_PING:
|
case ID_UNCONNECTED_PING:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
update(packet);
|
{
|
||||||
|
RakNet::BitStream bsIn(&packet->data[1], packet->length, false);
|
||||||
|
bsIn.IgnoreBytes((unsigned int) RakNet::RakNetGUID::size()); // Ignore GUID from received packet
|
||||||
|
|
||||||
|
|
||||||
|
if (Players::isPlayerExists(packet->guid))
|
||||||
|
update(packet, bsIn);
|
||||||
|
else
|
||||||
|
preInit(packet, bsIn);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TimerAPI::Tick();
|
TimerAPI::Tick();
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace mwmp
|
||||||
void processActorPacket(RakNet::Packet *packet);
|
void processActorPacket(RakNet::Packet *packet);
|
||||||
void processObjectPacket(RakNet::Packet *packet);
|
void processObjectPacket(RakNet::Packet *packet);
|
||||||
void processWorldstatePacket(RakNet::Packet *packet);
|
void processWorldstatePacket(RakNet::Packet *packet);
|
||||||
void update(RakNet::Packet *packet);
|
void update(RakNet::Packet *packet, RakNet::BitStream &bsIn);
|
||||||
|
|
||||||
unsigned short numberOfConnections() const;
|
unsigned short numberOfConnections() const;
|
||||||
unsigned int maxConnections() const;
|
unsigned int maxConnections() const;
|
||||||
|
@ -65,6 +65,7 @@ namespace mwmp
|
||||||
|
|
||||||
void postInit();
|
void postInit();
|
||||||
private:
|
private:
|
||||||
|
bool preInit(RakNet::Packet *packet, RakNet::BitStream &bsIn);
|
||||||
PacketPreInit::PluginContainer getPluginListSample();
|
PacketPreInit::PluginContainer getPluginListSample();
|
||||||
std::string serverPassword;
|
std::string serverPassword;
|
||||||
static Networking *sThis;
|
static Networking *sThis;
|
||||||
|
|
|
@ -54,9 +54,10 @@ void Players::newPlayer(RakNet::RakNetGUID guid)
|
||||||
|
|
||||||
Player *Players::getPlayer(RakNet::RakNetGUID guid)
|
Player *Players::getPlayer(RakNet::RakNetGUID guid)
|
||||||
{
|
{
|
||||||
if (players.count(guid) == 0)
|
auto it = players.find(guid);
|
||||||
|
if (it == players.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return players[guid];
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
TPlayers *Players::getPlayers()
|
TPlayers *Players::getPlayers()
|
||||||
|
@ -123,9 +124,10 @@ int Player::getLoadState()
|
||||||
|
|
||||||
Player *Players::getPlayer(unsigned short id)
|
Player *Players::getPlayer(unsigned short id)
|
||||||
{
|
{
|
||||||
if (slots.find(id) == slots.end())
|
auto it = slots.find(id);
|
||||||
|
if (it == slots.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return slots[id];
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
CellController::TContainer *Player::getCells()
|
CellController::TContainer *Player::getCells()
|
||||||
|
@ -174,3 +176,8 @@ void Player::forEachLoaded(std::function<void(Player *pl, Player *other)> func)
|
||||||
func(this, pl);
|
func(this, pl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Players::isPlayerExists(RakNet::RakNetGUID guid)
|
||||||
|
{
|
||||||
|
return players.find(guid) != players.end();
|
||||||
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ public:
|
||||||
static Player *getPlayer(unsigned short id);
|
static Player *getPlayer(unsigned short id);
|
||||||
static TPlayers *getPlayers();
|
static TPlayers *getPlayers();
|
||||||
static unsigned short getLastPlayerId();
|
static unsigned short getLastPlayerId();
|
||||||
|
static bool isPlayerExists(RakNet::RakNetGUID guid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static TPlayers players;
|
static TPlayers players;
|
||||||
|
|
Loading…
Reference in a new issue