mirror of
				https://github.com/ErikasKontenis/SabrehavenServer.git
				synced 2025-10-31 20:06:23 +01:00 
			
		
		
		
	commit client
This commit is contained in:
		
							
								
								
									
										300
									
								
								SabrehavenOTClient/modules/gamelib/protocollogin.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										300
									
								
								SabrehavenOTClient/modules/gamelib/protocollogin.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,300 @@ | ||||
| -- @docclass | ||||
| ProtocolLogin = extends(Protocol, "ProtocolLogin") | ||||
|  | ||||
| LoginServerError = 10 | ||||
| LoginServerTokenSuccess = 12 | ||||
| LoginServerTokenError = 13 | ||||
| LoginServerUpdate = 17 | ||||
| LoginServerMotd = 20 | ||||
| LoginServerUpdateNeeded = 30 | ||||
| LoginServerSessionKey = 40 | ||||
| LoginServerCharacterList = 100 | ||||
| LoginServerExtendedCharacterList = 101 | ||||
| LoginServerProxyList = 110 | ||||
|  | ||||
| -- Since 10.76 | ||||
| LoginServerRetry = 10 | ||||
| LoginServerErrorNew = 11 | ||||
|  | ||||
| function ProtocolLogin:login(host, port, accountName, accountPassword, authenticatorToken, stayLogged) | ||||
|   if string.len(host) == 0 or port == nil or port == 0 then | ||||
|     signalcall(self.onLoginError, self, tr("You must enter a valid server address and port.")) | ||||
|     return | ||||
|   end | ||||
|  | ||||
|   self.accountName = accountName | ||||
|   self.accountPassword = accountPassword | ||||
|   self.authenticatorToken = authenticatorToken | ||||
|   self.stayLogged = stayLogged | ||||
|   self.connectCallback = self.sendLoginPacket | ||||
|  | ||||
|   self:connect(host, port) | ||||
| end | ||||
|  | ||||
| function ProtocolLogin:cancelLogin() | ||||
|   self:disconnect() | ||||
| end | ||||
|  | ||||
| function ProtocolLogin:sendLoginPacket() | ||||
|   local msg = OutputMessage.create() | ||||
|   msg:addU8(ClientOpcodes.ClientEnterAccount) | ||||
|   msg:addU16(g_game.getOs()) | ||||
|   if g_game.getCustomProtocolVersion() > 0 then | ||||
|     msg:addU16(g_game.getCustomProtocolVersion())   | ||||
|   else | ||||
|     msg:addU16(g_game.getProtocolVersion()) | ||||
|   end | ||||
|  | ||||
|   if g_game.getFeature(GameClientVersion) then | ||||
|     msg:addU32(g_game.getClientVersion()) | ||||
|   end | ||||
|  | ||||
|   if g_game.getFeature(GameContentRevision) then | ||||
|     msg:addU16(g_things.getContentRevision()) | ||||
|     msg:addU16(0) | ||||
|   else | ||||
|     msg:addU32(g_things.getDatSignature()) | ||||
|   end | ||||
|   msg:addU32(g_sprites.getSprSignature()) | ||||
|   msg:addU32(PIC_SIGNATURE) | ||||
|  | ||||
|   if g_game.getFeature(GamePreviewState) then | ||||
|     msg:addU8(0) | ||||
|   end | ||||
|  | ||||
|   local offset = msg:getMessageSize() | ||||
|   if g_game.getFeature(GameLoginPacketEncryption) then | ||||
|     -- first RSA byte must be 0 | ||||
|     msg:addU8(0) | ||||
|  | ||||
|     -- xtea key | ||||
|     self:generateXteaKey() | ||||
|     local xteaKey = self:getXteaKey() | ||||
|     msg:addU32(xteaKey[1]) | ||||
|     msg:addU32(xteaKey[2]) | ||||
|     msg:addU32(xteaKey[3]) | ||||
|     msg:addU32(xteaKey[4]) | ||||
|   end | ||||
|  | ||||
|   if g_game.getFeature(GameAccountNames) then | ||||
|     msg:addString(self.accountName) | ||||
|   else | ||||
| 	msg:addU32(tonumber(self.accountName)) | ||||
|     msg:addU32(tonumber(self.accountName)) | ||||
|   end | ||||
|  | ||||
|   msg:addString(self.accountPassword) | ||||
|  | ||||
|   if self.getLoginExtendedData then | ||||
|     local data = self:getLoginExtendedData() | ||||
|     msg:addString(data) | ||||
|   else | ||||
|     msg:addString("OTCv8") | ||||
|     local version = g_app.getVersion():split(" ")[1]:gsub("%.", "") | ||||
|     if version:len() == 2 then | ||||
|       version = version .. "0"  | ||||
|     end | ||||
|     msg:addU16(tonumber(version)) | ||||
|   end | ||||
|  | ||||
|   local paddingBytes = g_crypt.rsaGetSize() - (msg:getMessageSize() - offset) | ||||
|   assert(paddingBytes >= 0) | ||||
|   for i = 1, paddingBytes do | ||||
|     msg:addU8(math.random(0, 0xff)) | ||||
|   end | ||||
|  | ||||
|   if g_game.getFeature(GameLoginPacketEncryption) then | ||||
|     msg:encryptRsa() | ||||
|   end | ||||
|  | ||||
|   if g_game.getFeature(GameOGLInformation) then | ||||
|     msg:addU8(1) --unknown | ||||
|     msg:addU8(1) --unknown | ||||
|  | ||||
|     if g_game.getClientVersion() >= 1072 then | ||||
|       msg:addString(string.format('%s %s', g_graphics.getVendor(), g_graphics.getRenderer())) | ||||
|     else | ||||
|       msg:addString(g_graphics.getRenderer()) | ||||
|     end | ||||
|     msg:addString(g_graphics.getVersion()) | ||||
|   end | ||||
|  | ||||
|   -- add RSA encrypted auth token | ||||
|   if g_game.getFeature(GameAuthenticator) then | ||||
|     offset = msg:getMessageSize() | ||||
|  | ||||
|     -- first RSA byte must be 0 | ||||
|     msg:addU8(0) | ||||
|     msg:addString(self.authenticatorToken) | ||||
|  | ||||
|     if g_game.getFeature(GameSessionKey) then | ||||
|       msg:addU8(booleantonumber(self.stayLogged)) | ||||
|     end | ||||
|  | ||||
|     paddingBytes = g_crypt.rsaGetSize() - (msg:getMessageSize() - offset) | ||||
|     assert(paddingBytes >= 0) | ||||
|     for i = 1, paddingBytes do | ||||
|       msg:addU8(math.random(0, 0xff)) | ||||
|     end | ||||
|  | ||||
|     msg:encryptRsa() | ||||
|   end | ||||
|  | ||||
|   if g_game.getFeature(GamePacketSizeU32) then | ||||
|     self:enableBigPackets() | ||||
|   end | ||||
|  | ||||
|   if g_game.getFeature(GameProtocolChecksum) then | ||||
|     self:enableChecksum() | ||||
|   end | ||||
|  | ||||
|   self:send(msg) | ||||
|   if g_game.getFeature(GameLoginPacketEncryption) then | ||||
|     self:enableXteaEncryption() | ||||
|   end | ||||
|   self:recv() | ||||
| end | ||||
|  | ||||
| function ProtocolLogin:onConnect() | ||||
|   self.gotConnection = true | ||||
|   self:connectCallback() | ||||
|   self.connectCallback = nil | ||||
| end | ||||
|  | ||||
| function ProtocolLogin:onRecv(msg) | ||||
|   while not msg:eof() do | ||||
|     local opcode = msg:getU8() | ||||
|     if opcode == LoginServerErrorNew then | ||||
|       self:parseError(msg) | ||||
|     elseif opcode == LoginServerError then | ||||
|       self:parseError(msg) | ||||
|     elseif opcode == LoginServerMotd then | ||||
|       self:parseMotd(msg) | ||||
|     elseif opcode == LoginServerUpdateNeeded then | ||||
|       signalcall(self.onLoginError, self, tr("Client needs update.")) | ||||
|     elseif opcode == LoginServerTokenSuccess then | ||||
|       local unknown = msg:getU8() | ||||
|     elseif opcode == LoginServerTokenError then | ||||
|       -- TODO: prompt for token here | ||||
|       local unknown = msg:getU8() | ||||
|       signalcall(self.onLoginError, self, tr("Invalid authentification token.")) | ||||
|     elseif opcode == LoginServerCharacterList then | ||||
|       self:parseCharacterList(msg) | ||||
|     elseif opcode == LoginServerExtendedCharacterList then | ||||
|       self:parseExtendedCharacterList(msg) | ||||
|     elseif opcode == LoginServerUpdate then | ||||
|       local signature = msg:getString() | ||||
|       signalcall(self.onUpdateNeeded, self, signature)       | ||||
|     elseif opcode == LoginServerSessionKey then | ||||
|       self:parseSessionKey(msg) | ||||
|     elseif opcode == LoginServerProxyList then | ||||
|       local proxies = {} | ||||
|       local proxiesCount = msg:getU8() | ||||
|       for i=1, proxiesCount do | ||||
|         local host = msg:getString() | ||||
|         local port = msg:getU16() | ||||
|         local priority = msg:getU16()         | ||||
|         table.insert(proxies, {host=host, port=port, priority=priority}) | ||||
|       end       | ||||
|       signalcall(self.onProxyList, self, proxies) | ||||
|     else | ||||
|       self:parseOpcode(opcode, msg) | ||||
|     end | ||||
|   end | ||||
|   self:disconnect() | ||||
| end | ||||
|  | ||||
| function ProtocolLogin:parseError(msg) | ||||
|   local errorMessage = msg:getString() | ||||
|   signalcall(self.onLoginError, self, errorMessage) | ||||
| end | ||||
|  | ||||
| function ProtocolLogin:parseMotd(msg) | ||||
|   local motd = msg:getString() | ||||
|   signalcall(self.onMotd, self, motd) | ||||
| end | ||||
|  | ||||
| function ProtocolLogin:parseSessionKey(msg) | ||||
|   local sessionKey = msg:getString() | ||||
|   signalcall(self.onSessionKey, self, sessionKey) | ||||
| end | ||||
|  | ||||
| function ProtocolLogin:parseCharacterList(msg) | ||||
|   local characters = {} | ||||
|  | ||||
|   if g_game.getClientVersion() > 1010 then | ||||
|     local worlds = {} | ||||
|  | ||||
|     local worldsCount = msg:getU8() | ||||
|     for i=1, worldsCount do | ||||
|       local world = {} | ||||
|       local worldId = msg:getU8() | ||||
|       world.worldName = msg:getString() | ||||
|       world.worldIp = msg:getString() | ||||
|       world.worldPort = msg:getU16() | ||||
|       world.previewState = msg:getU8() | ||||
|       worlds[worldId] = world | ||||
|     end | ||||
|  | ||||
|     local charactersCount = msg:getU8() | ||||
|     for i=1, charactersCount do | ||||
|       local character = {} | ||||
|       local worldId = msg:getU8() | ||||
|       character.name = msg:getString() | ||||
|       character.worldName = worlds[worldId].worldName | ||||
|       character.worldIp = worlds[worldId].worldIp | ||||
|       character.worldPort = worlds[worldId].worldPort | ||||
|       character.previewState = worlds[worldId].previewState | ||||
|       characters[i] = character | ||||
|     end | ||||
|  | ||||
|   else | ||||
|     local charactersCount = msg:getU8() | ||||
|     for i=1,charactersCount do | ||||
|       local character = {} | ||||
|       character.name = msg:getString() | ||||
|       character.worldName = msg:getString() | ||||
|       character.worldIp = iptostring(msg:getU32()) | ||||
|       character.worldPort = msg:getU16() | ||||
|  | ||||
|       if g_game.getFeature(GamePreviewState) then | ||||
|         character.previewState = msg:getU8() | ||||
|       end | ||||
|  | ||||
|       characters[i] = character | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   local account = {} | ||||
|   if g_game.getProtocolVersion() > 1077 then | ||||
|     account.status = msg:getU8() | ||||
|     account.subStatus = msg:getU8() | ||||
|  | ||||
|     account.premDays = msg:getU32() | ||||
|     if account.premDays ~= 0 and account.premDays ~= 65535 then | ||||
|       account.premDays = math.floor((account.premDays - os.time()) / 86400) | ||||
|     end | ||||
|   else | ||||
|     account.status = AccountStatus.Ok | ||||
|     account.premDays = msg:getU16() | ||||
|     account.subStatus = account.premDays > 0 and SubscriptionStatus.Premium or SubscriptionStatus.Free | ||||
|   end | ||||
|  | ||||
|   signalcall(self.onCharacterList, self, characters, account) | ||||
| end | ||||
|  | ||||
| function ProtocolLogin:parseExtendedCharacterList(msg) | ||||
|   local characters = msg:getTable() | ||||
|   local account = msg:getTable() | ||||
|   local otui = msg:getString() | ||||
|   signalcall(self.onCharacterList, self, characters, account, otui) | ||||
| end | ||||
|  | ||||
| function ProtocolLogin:parseOpcode(opcode, msg) | ||||
|   signalcall(self.onOpcode, self, opcode, msg) | ||||
| end | ||||
|  | ||||
| function ProtocolLogin:onError(msg, code) | ||||
|   local text = translateNetworkError(code, self:isConnecting(), msg) | ||||
|   signalcall(self.onLoginError, self, text) | ||||
| end | ||||
		Reference in New Issue
	
	Block a user
	 ErikasKontenis
					ErikasKontenis