Merge branch '0.7.0' of https://github.com/TES3MP/openmw-tes3mp into 0.7.0

remotes/1728160796594174844/tmp_0.7.0-alpha
David Cernat 7 years ago
commit 6c50d4199b

@ -1,6 +1,9 @@
TES3MP
======
Copyright (c) 2008-2015, OpenMW Team
Copyright (c) 2016-2018, TES3MP Team
[![Build Status](https://travis-ci.org/TES3MP/openmw-tes3mp.svg?branch=master)](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.

@ -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);
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)
{
if (packet->data[0] == ID_GAME_PREINIT)
{
DEBUG_PRINTF("ID_GAME_PREINIT");
PacketPreInit::PluginContainer plugins;
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "%s sent wrong first packet (ID_GAME_PREINIT was expected)",
packet->systemAddress.ToString());
peer->CloseConnection(packet->systemAddress, true);
}
PacketPreInit packetPreInit(peer);
packetPreInit.SetReadStream(&bsIn);
packetPreInit.setChecksums(&plugins);
packetPreInit.Read();
DEBUG_PRINTF("ID_GAME_PREINIT");
PacketPreInit::PluginContainer plugins;
if (!packetPreInit.isPacketValid())
{
LOG_APPEND(Log::LOG_ERROR, "Invalid packetPreInit");
peer->CloseConnection(packet->systemAddress, false); // close connection without notification
return;
}
PacketPreInit packetPreInit(peer);
packetPreInit.SetReadStream(&bsIn);
packetPreInit.setChecksums(&plugins);
packetPreInit.Read();
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 (!packetPreInit.isPacketValid() || plugins.empty())
{
LOG_APPEND(Log::LOG_ERROR, "Invalid packetPreInit");
peer->CloseConnection(packet->systemAddress, false); // close connection without notification
return false;
}
// 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
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))
{
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "%s was allowed to connect", packet->systemAddress.ToString());
PacketPreInit::PluginContainer tmp;
packetPreInit.setChecksums(&tmp);
packetPreInit.Send(packet->systemAddress);
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;
}
return;
else // name is incorrect
break;
}
}
RakNet::BitStream bs;
packetPreInit.SetSendStream(&bs);
playerPacketController->SetStream(&bsIn, 0);
// 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);
Players::newPlayer(packet->guid);
player = Players::getPlayer(packet->guid);
return;
return true;
}
else if (playerPacketController->ContainsPacket(packet->data[0]))
return false;
}
void Networking::update(RakNet::Packet *packet, RakNet::BitStream &bsIn)
{
if (playerPacketController->ContainsPacket(packet->data[0]))
{
playerPacketController->SetStream(&bsIn, 0);
playerPacketController->SetStream(&bsIn, nullptr);
processPlayerPacket(packet);
}
else if (actorPacketController->ContainsPacket(packet->data[0]))
@ -531,8 +527,17 @@ int Networking::mainLoop()
case ID_UNCONNECTED_PING:
break;
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;
}
}
}
TimerAPI::Tick();

@ -29,7 +29,7 @@ namespace mwmp
void processActorPacket(RakNet::Packet *packet);
void processObjectPacket(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 int maxConnections() const;
@ -65,6 +65,7 @@ namespace mwmp
void postInit();
private:
bool preInit(RakNet::Packet *packet, RakNet::BitStream &bsIn);
PacketPreInit::PluginContainer getPluginListSample();
std::string serverPassword;
static Networking *sThis;

@ -54,9 +54,10 @@ void Players::newPlayer(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 players[guid];
return it->second;
}
TPlayers *Players::getPlayers()
@ -123,9 +124,10 @@ int Player::getLoadState()
Player *Players::getPlayer(unsigned short id)
{
if (slots.find(id) == slots.end())
auto it = slots.find(id);
if (it == slots.end())
return nullptr;
return slots[id];
return it->second;
}
CellController::TContainer *Player::getCells()
@ -174,3 +176,8 @@ void Player::forEachLoaded(std::function<void(Player *pl, Player *other)> func)
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 TPlayers *getPlayers();
static unsigned short getLastPlayerId();
static bool isPlayerExists(RakNet::RakNetGUID guid);
private:
static TPlayers players;

Loading…
Cancel
Save