229 lines
6.1 KiB
Lua

EnterGameV2Protocol = {}
EnterGameV2Protocol.__index = EnterGameV2Protocol
EnterGameV2Protocol.new = function(session)
if type(session) ~= 'string' then
return error("You need to specify string session for EnterGameV2Protocol")
end
local data = {}
data.socket = nil
data.terminated = false
data.reconnectEvent = nil
data.connected = false
data.session = session
data.sendQueue = {}
data.sendQueueMsgId = 1
data.loginTimeoutEvent = nil
setmetatable(data, EnterGameV2Protocol)
return data
end
function EnterGameV2Protocol:destroy()
self.terminated = true
self.sendQueue = {}
if self.loginTimeoutEvent then
removeEvent(self.loginTimeoutEvent)
self.loginTimeoutEvent = nil
end
self:reset()
end
function EnterGameV2Protocol:reset()
self.connected = false
if self.reconnectEvent then
removeEvent(self.reconnectEvent)
self.reconnectEvent = nil
end
if self.socket then
self.socket.close()
self.socket = nil
end
end
function EnterGameV2Protocol:setUrl(url)
if self.terminated then
return false
end
self:reset()
if self.url ~= url then
self.sendQueue = {}
self.sendQueueMsgId = 1
if self.loginTimeoutEvent then
removeEvent(self.loginTimeoutEvent)
self.loginTimeoutEvent = nil
end
end
if type(url) ~= 'string' or not url:lower():find("ws") then
g_logger.error("Invalid url for EnterGameV2Protocol:\n" .. url)
return false
end
self.url = url
self.socket = HTTP.WebSocketJSON(url, {
onOpen = function(message, websocketId)
if self.terminated or not self.socket or self.socket.id ~= websocketId then return end
self.connected = true
self:sendFirstMessage()
end,
onMessage = function(message, websocketId)
if self.terminated or not self.socket or self.socket.id ~= websocketId then return end
self:onSocketMessage(message)
end,
onClose = function(message, websocketId)
if self.terminated or not self.socket or self.socket.id ~= websocketId then return end
self.connected = false
self:scheduleReconnect()
end,
onError = function(message, websocketId)
if self.terminated or not self.socket or self.socket.id ~= websocketId then return end
self.connected = false
self:scheduleReconnect()
end
})
return true
end
function EnterGameV2Protocol:isConnected()
return self.socket and self.connected
end
function EnterGameV2Protocol:scheduleReconnect()
if self.socket then
self.connected = false
self.socket.close()
self.socket = nil
end
if self.terminated then return end
if self.reconnectEvent then return end
self.reconnectEvent = scheduleEvent(function() self:reconnect() end, 500)
end
function EnterGameV2Protocol:login(account, password, token, callback)
self:send({
type="login",
account=account,
password=password,
token=token,
})
if self.loginTimeoutEvent then
removeEvent(self.loginTimeoutEvent)
end
self.loginTimeoutEvent = scheduleEvent(function()
self.loginTimeoutEvent = nil
self.onLogin({error="Connection timeout"})
end, 10000)
end
function EnterGameV2Protocol:logout()
self:send({
type="logout"
})
end
function EnterGameV2Protocol:register(name, email, password, callback)
end
function EnterGameV2Protocol:createCharacter(name, gender, vocation, town)
self:send({
type="createcharacter",
name=name,
gender=gender,
vocation=vocation,
town=town
})
end
function EnterGameV2Protocol:updateSettings(settings)
self:send({
type="settings",
settings=settings
})
end
-- private functions
function EnterGameV2Protocol:reconnect()
if #self.sendQueue > 1 then
self.sendQueue = {} -- TEMPORARY
end
self.reconnectEvent = nil
if self.terminated then return end
self:setUrl(self.url)
end
function EnterGameV2Protocol:send(data)
if type(data) ~= "table" then
return error("data should be table")
end
data["id"] = self.sendQueueMsgId
table.insert(self.sendQueue, {id=self.sendQueueMsgId, msg=json.encode(data)})
self.sendQueueMsgId = self.sendQueueMsgId + 1
if self.socket then
self.socket.send(self.sendQueue[#self.sendQueue].msg)
end
end
function EnterGameV2Protocol:sendFirstMessage()
self.socket.send({type="init", session=self.session})
for i, msg in ipairs(self.sendQueue) do
self.socket.send(msg.msg)
end
end
function EnterGameV2Protocol:onSocketMessage(message)
local lastId = message["lastId"]
if type(lastId) == 'number' then -- clear send queue
while #self.sendQueue > 0 do
local id = self.sendQueue[1].id
if id < lastId then
break
end
table.remove(self.sendQueue, 1)
end
end
if message["type"] == "ping" then
self.socket.send({type="ping"})
elseif message["type"] == "login" then
if self.loginTimeoutEvent then
removeEvent(self.loginTimeoutEvent)
self.loginTimeoutEvent = nil
end
if self.onLogin then
self.onLogin(message)
end
elseif message["type"] == "logout" then
if self.onLogout then
self.onLogout()
end
elseif message["type"] == "qauth" then
if self.onQAuth then
self.onQAuth(message["token"])
end
elseif message["type"] == "characters" then
if self.onCharacters then
self.onCharacters(message["characters"])
end
elseif message["type"] == "message" then
if self.onMessage then
self.onMessage(message["title"], message["text"])
end
elseif message["type"] == "loading" then
if self.onMessage then
self.onLoading(message["title"], message["text"])
end
elseif message["type"] == "news" then
if self.onNews then
self.onNews(message["news"])
end
elseif message["type"] == "motd" then
if self.onMotd then
self.onMotd(message["text"])
end
elseif message["type"] == "createcharacter" then
if self.onMessage then
self.onCharacterCreate(message["error"], message["message"])
end
end
end