diff --git a/common/emu_oplist.h b/common/emu_oplist.h index b58e45827..aa8190720 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -534,6 +534,7 @@ N(OP_Stamina), N(OP_Stun), N(OP_Surname), N(OP_SwapSpell), +N(OP_SystemFingerprint), N(OP_TargetBuffs), N(OP_TargetCommand), N(OP_TargetHoTT), diff --git a/loginserver/client.h b/loginserver/client.h index 4c5ca2cb7..cc24ebe23 100644 --- a/loginserver/client.h +++ b/loginserver/client.h @@ -138,6 +138,13 @@ public: */ unsigned int GetPlaySequence() const { return m_play_sequence_id; } + /** + * Gets the client version + * + * @return + */ + LSClientVersion GetClientVersion() const { return m_client_version; } + /** * Gets the connection for this client * diff --git a/loginserver/client_manager.cpp b/loginserver/client_manager.cpp index 7bb352929..8567c35b4 100644 --- a/loginserver/client_manager.cpp +++ b/loginserver/client_manager.cpp @@ -88,6 +88,46 @@ ClientManager::ClientManager() clients.push_back(c); } ); + + int larion_port = server.config.GetVariableInt("client_configuration", "larion_port", 15900); + + EQStreamManagerInterfaceOptions larion_opts(larion_port, false, false); + + larion_stream = new EQ::Net::EQStreamManager(larion_opts); + larion_ops = new RegularOpcodeManager; + + opcodes_path = fmt::format( + "{}/{}", + path.GetServerPath(), + server.config.GetVariableString( + "client_configuration", + "larion_opcodes", + "login_opcodes.conf" + ) + ); + + if (!larion_ops->LoadOpcodes(opcodes_path.c_str())) { + LogError( + "ClientManager fatal error: couldn't load opcodes for Larion file [{0}]", + server.config.GetVariableString("client_configuration", "larion_opcodes", "login_opcodes.conf") + ); + + run_server = false; + } + + larion_stream->OnNewConnection( + [this](std::shared_ptr stream) { + LogInfo( + "New Larion client connection from [{0}:{1}]", + long2ip(stream->GetRemoteIP()), + stream->GetRemotePort() + ); + + stream->SetOpcodeManager(&larion_ops); + Client* c = new Client(stream, cv_larion); + clients.push_back(c); + } + ); } ClientManager::~ClientManager() diff --git a/loginserver/client_manager.h b/loginserver/client_manager.h index 6a8c31164..23aff232e 100644 --- a/loginserver/client_manager.h +++ b/loginserver/client_manager.h @@ -55,6 +55,8 @@ private: EQ::Net::EQStreamManager *titanium_stream; OpcodeManager *sod_ops; EQ::Net::EQStreamManager *sod_stream; + OpcodeManager *larion_ops; + EQ::Net::EQStreamManager* larion_stream; }; #endif diff --git a/loginserver/login_types.h b/loginserver/login_types.h index 3f4f20d59..1c8054a37 100644 --- a/loginserver/login_types.h +++ b/loginserver/login_types.h @@ -83,7 +83,8 @@ struct PlayEverquestResponse_Struct { enum LSClientVersion { cv_titanium, - cv_sod + cv_sod, + cv_larion }; enum LSClientStatus { diff --git a/loginserver/login_util/login_opcodes_larion.conf b/loginserver/login_util/login_opcodes_larion.conf new file mode 100644 index 000000000..8bc205388 --- /dev/null +++ b/loginserver/login_util/login_opcodes_larion.conf @@ -0,0 +1,14 @@ +#EQEmu Public Login Server OPCodes +OP_SessionReady=0x0001 +OP_Login=0x0002 +OP_ServerListRequest=0x0004 +OP_PlayEverquestRequest=0x000d +OP_PlayEverquestResponse=0x0022 +OP_ChatMessage=0x0017 +OP_LoginAccepted=0x0018 +OP_ServerListResponse=0x0019 +OP_Poll=0x0029 +OP_EnterChat=0x000f +OP_PollResponse=0x0011 +OP_SystemFingerprint=0x0016 +OP_ExpansionList=0x0030 \ No newline at end of file diff --git a/loginserver/server_manager.cpp b/loginserver/server_manager.cpp index 4dfe66c4a..f46a6c925 100644 --- a/loginserver/server_manager.cpp +++ b/loginserver/server_manager.cpp @@ -137,7 +137,7 @@ std::unique_ptr ServerManager::CreateServerListPacket(Clien use_local_ip ? "Local" : "Remote" ); - world_server->SerializeForClientServerList(buf, use_local_ip); + world_server->SerializeForClientServerList(buf, use_local_ip, client->GetClientVersion()); } return std::make_unique(OP_ServerListResponse, buf); diff --git a/loginserver/world_server.cpp b/loginserver/world_server.cpp index 1f7fc404e..b43651fd7 100644 --- a/loginserver/world_server.cpp +++ b/loginserver/world_server.cpp @@ -977,7 +977,7 @@ bool WorldServer::ValidateWorldServerAdminLogin( return false; } -void WorldServer::SerializeForClientServerList(SerializeBuffer &out, bool use_local_ip) const +void WorldServer::SerializeForClientServerList(SerializeBuffer& out, bool use_local_ip, LSClientVersion version) const { // see LoginClientServerData_Struct if (use_local_ip) { @@ -987,19 +987,31 @@ void WorldServer::SerializeForClientServerList(SerializeBuffer &out, bool use_lo out.WriteString(GetRemoteIP()); } - switch (GetServerListID()) { - case LS::ServerType::Legends: - out.WriteInt32(LS::ServerTypeFlags::Legends); - break; - case LS::ServerType::Preferred: - out.WriteInt32(LS::ServerTypeFlags::Preferred); - break; - default: - out.WriteInt32(LS::ServerTypeFlags::Standard); - break; + if (version == cv_larion) { + out.WriteUInt32(9000); + } + + switch (GetServerListID()) { + case LS::ServerType::Legends: + out.WriteInt32(LS::ServerTypeFlags::Legends); + break; + case LS::ServerType::Preferred: + out.WriteInt32(LS::ServerTypeFlags::Preferred); + break; + default: + out.WriteInt32(LS::ServerTypeFlags::Standard); + break; + } + if (version == cv_larion) { + auto server_id = GetServerId(); + //if this is 0, the client will not show the server in the list + out.WriteUInt32(1); + out.WriteUInt32(server_id); + } + else { + out.WriteUInt32(GetServerId()); } - out.WriteUInt32(GetServerId()); out.WriteString(GetServerLongName()); out.WriteString("us"); // country code out.WriteString("en"); // language code diff --git a/loginserver/world_server.h b/loginserver/world_server.h index 57f9ac150..df5324240 100644 --- a/loginserver/world_server.h +++ b/loginserver/world_server.h @@ -7,6 +7,7 @@ #include "../common/packet_dump.h" #include "database.h" #include "../common/event/timer.h" +#include "login_types.h" #include #include @@ -149,7 +150,7 @@ public: bool HandleNewLoginserverRegisteredOnly(Database::DbWorldRegistration &world_registration); bool HandleNewLoginserverInfoUnregisteredAllowed(Database::DbWorldRegistration &world_registration); - void SerializeForClientServerList(class SerializeBuffer& out, bool use_local_ip) const; + void SerializeForClientServerList(class SerializeBuffer& out, bool use_local_ip, LSClientVersion version) const; private: