Version 1.4 - Websockets and bug fixes

This commit is contained in:
OTCv8
2019-11-26 02:32:51 +01:00
parent 1072671986
commit c750ea65f8
29 changed files with 426 additions and 124 deletions

View File

@@ -50,11 +50,7 @@ StaticMainWindow
@onSetup: |
g_keyboard.bindKeyPress('Up', function() self:getChildById('characters'):focusPreviousChild(KeyboardFocusReason) end, self)
g_keyboard.bindKeyPress('Down', function() self:getChildById('characters'):focusNextChild(KeyboardFocusReason) end, self)
if g_game.getFeature(GamePreviewState) then
self:setSize({width = 350, height = 400})
else
self:setSize({width = 250, height = 248})
end
self:setSize({width = 350, height = 400})
TextList
id: characters

View File

@@ -9,10 +9,6 @@ local protocolLogin
local server = nil
local versionsFound = false
local newLogin = nil
local newLoginUrl = nil
local newLoginEvent
local customServerSelectorPanel
local serverSelectorPanel
local serverSelector
@@ -21,6 +17,8 @@ local serverHostTextEdit
local rememberPasswordBox
local protos = {"740", "760", "772", "800", "810", "854", "860", "1077", "1090", "1096", "1098", "1099", "1100"}
local webSocket
local webSocketLoginPacket
-- private functions
local function onProtocolError(protocol, message, errorCode)
@@ -125,6 +123,10 @@ local function onHTTPResult(data, err)
if #incorrectThings > 0 then
g_logger.info(incorrectThings)
if Updater then
if webSocket then
webSocket:close()
webSocket = nil
end
return Updater.updateThings(things, incorrectThings)
else
return EnterGame.onError(incorrectThings)
@@ -175,6 +177,10 @@ local function onHTTPResult(data, err)
end
end
if webSocket then
webSocket:close()
webSocket = nil
end
onCharacterList(nil, characters, account, nil)
end
@@ -244,7 +250,10 @@ end
function EnterGame.terminate()
g_keyboard.unbindKeyDown('Ctrl+G')
removeEvent(newLoginEvent)
if webSocket then
webSocket.close()
webSocket = nil
end
enterGame:destroy()
if newLogin then
@@ -269,7 +278,7 @@ function EnterGame.show()
enterGame:raise()
enterGame:focus()
enterGame:getChildById('accountNameTextEdit'):focus()
EnterGame.checkNewLogin()
EnterGame.checkWebsocket()
end
function EnterGame.hide()
@@ -294,33 +303,74 @@ function EnterGame.clearAccountFields()
g_settings.remove('password')
end
function EnterGame.hideNewLogin()
newLogin:hide()
newLoginUrl = nil
end
function EnterGame.checkNewLoginEvent()
newLoginEvent = scheduleEvent(function() EnterGame.checkNewLoginEvent() end, 1000)
EnterGame.checkNewLogin()
end
function EnterGame.checkNewLogin()
if not newLoginUrl then
function EnterGame.checkWebsocket()
if enterGame:isHidden() then return end
local url = serverHostTextEdit:getText()
if url:find("ws://") == nil and url:find("wss://") == nil then
if webSocket then
webSocket:close()
webSocket = nil
end
return
end
local url = newLoginUrl
HTTP.postJSON(newLoginUrl, { quick = 1 }, function(data, err)
if url ~= newLoginUrl then return end
if err then return end
if not data["qrcode"] then return end
newLogin.qrcode:setImageSourceBase64(data["qrcode"])
newLogin.code:setText(data["code"])
if enterGame:isHidden() then return end
if newLogin:isHidden() then
newLogin:show()
newLogin:raise()
if webSocket then
if webSocket.url == url then
if newLogin:isHidden() and newLogin.code:getText():len() > 1 then
newLogin:show()
newLogin:raise()
end
return
end
end)
webSocket:close()
webSocket = nil
end
newLogin.code:setText("")
webSocket = HTTP.WebSocketJSON(url, {
onOpen = function(message, webSocketId)
if webSocket and webSocket.id == webSocketId then
webSocket.send({type="init", uid=G.uuid, version=APP_VERSION})
end
end,
onMessage = function(message, webSocketId)
if webSocket and webSocket.id == webSocketId then
if message.type == "login" then
webSocketLoginPacket = nil
onHTTPResult(message, nil)
elseif message.type == "quick_login" and message.code and message.qrcode then
EnterGame.showNewLogin(message.code, message.qrcode)
end
end
end,
onClose = function(message, webSocketId)
if webSocket and webSocket.id == webSocketId then
webSocket = nil
if webSocketLoginPacket then
webSocketLoginPacket = nil
onHTTPResult(nil, "WebSocket disconnected")
end
EnterGame.checkWebsocket() -- reconnect
end
end,
onError = function(message, webSocketId)
if webSocket and webSocket.id == webSocketId then
-- handle error
end
end
})
end
function EnterGame.hideNewLogin()
newLogin:hide()
end
function EnterGame.showNewLogin(code, qrcode)
if enterGame:isHidden() then return end
newLogin.code:setText(code)
newLogin.qrcode:setQRCode(qrcode, 1)
if newLogin:isHidden() then
newLogin:show()
newLogin:raise()
end
end
function EnterGame.onServerChange()
@@ -338,8 +388,7 @@ function EnterGame.onServerChange()
end
if Servers and Servers[server] ~= nil then
serverHostTextEdit:setText(Servers[server])
newLoginUrl = Servers[server]
EnterGame.checkNewLogin()
EnterGame.checkWebsocket()
end
end
@@ -371,6 +420,9 @@ function EnterGame.doLogin()
g_settings.set('client-version', G.clientVersion)
g_settings.save()
if G.host:find("ws://") ~= nil or G.host:find("wss://") ~= nil then
return EnterGame.doLoginWs()
end
if G.host:find("http") ~= nil then
return EnterGame.doLoginHttp()
end
@@ -446,6 +498,36 @@ function EnterGame.doLogin()
end
end
function EnterGame.doLoginWs()
-- PREVIEW, need to implement websocket reconnect and error handling
if G.host == nil or G.host:len() < 10 then
return EnterGame.onError("Invalid server url: " .. G.host)
end
if not webSocket then
return EnterGame.onError("There's no websocket connection to: " .. G.host)
end
loadBox = displayCancelBox(tr('Please wait'), tr('Connecting to login server...'))
connect(loadBox, { onCancel = function(msgbox)
loadBox = nil
webSocketLoginPacket = nil
EnterGame.show()
end })
local data = {
type = "login",
account = G.account,
password = G.password,
token = G.authenticatorToken,
version = APP_VERSION,
uid = G.UUID
}
webSocketLoginPacket = data
webSocket.send(data)
EnterGame.hide()
end
function EnterGame.doLoginHttp()
if G.host == nil or G.host:len() < 10 then
return EnterGame.onError("Invalid server url: " .. G.host)

View File

@@ -4,21 +4,33 @@ StaticWindow
margin-right: 20
id: newLoginPanel
width: 230
height: 330
height: 350
!text: tr('Quick Login & Registration')
Label
id: qrcode
width: 200
height: 180
height: 200
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
image-fixed-ratio: true
image-smooth: false
margin-top: 5
Label
anchors.top: prev.bottom
anchors.left: prev.left
anchors.right: prev.right
id: quathlogo
width: 66
height: 40
anchors.verticalCenter: prev.verticalCenter
anchors.horizontalCenter: prev.horizontalCenter
image-fixed-ratio: true
image-smooth: false
image-source: /images/ui/qauth
Label
anchors.top: qrcode.bottom
anchors.left: qrcode.left
anchors.right: qrcode.right
text-align: center
text-auto-resize: true
!text: tr("Scan QR code or process\nbellow code to register or login")

View File

@@ -25,7 +25,7 @@ function terminate()
end
function show()
if Services.feedback == nil or Services.feedback:len() < 4 then
if not Services or not Services.feedback or Services.feedback:len() < 4 then
return
end

View File

@@ -303,8 +303,8 @@ function setOption(key, value, force)
end
--elseif key == 'ignoreServerDirection' then
-- g_game.ignoreServerDirection(value)
elseif key == 'realDirection' then
g_game.showRealDirection(value)
--elseif key == 'realDirection' then
-- g_game.showRealDirection(value)
elseif key == 'hotkeyDelay' then
generalPanel:getChildById('hotkeyDelayLabel'):setText(tr('Hotkey delay: %s ms', value))
elseif key == 'walkFirstStepDelay' then

View File

@@ -48,6 +48,11 @@ function init()
end
updateFps()
if not Services or not Services.feedback or Services.feedback:len() < 4 then
topMenu.reportBug:setVisible(false)
topMenu.reportBug:setWidth(0)
end
if HIDE_TOPMENU then
topMenu:setHeight(0)

View File

@@ -1,5 +1,6 @@
HTTP = {
timeout=5,
websocketTimeout=15,
imageId=1000,
images={},
operations={}
@@ -55,6 +56,30 @@ function HTTP.downloadImage(url, callback)
return operation
end
function HTTP.webSocket(url, callbacks, jsonWebsocket)
local operation = g_http.ws(url, HTTP.websocketTimeout)
HTTP.operations[operation] = {type="ws", json=jsonWebsocket, url=url, callbacks=callbacks}
return {
id = operation,
url = url,
close = function()
g_http.wsClose(operation)
end,
send = function(message)
if type(message) == "table" then
message = json.encode(message)
end
g_http.wsSend(operation, message)
end
}
end
HTTP.WebSocket = HTTP.webSocket
function HTTP.webSocketJSON(url, callbacks)
return HTTP.webSocket(url, callbacks, true)
end
HTTP.WebSocketJSON = HTTP.webSocketJSON
function HTTP.cancel(operationId)
return g_http.cancel(operationId)
end
@@ -71,6 +96,9 @@ function HTTP.onGet(operationId, url, err, data)
local status, result = pcall(function() return json.decode(data) end)
if not status then
err = "JSON ERROR: " .. result
if data and data:len() > 0 then
err = err .. " (" .. data:sub(1, 100) .. ")"
end
end
data = result
end
@@ -99,6 +127,9 @@ function HTTP.onPost(operationId, url, err, data)
local status, result = pcall(function() return json.decode(data) end)
if not status then
err = "JSON ERROR: " .. result
if data and data:len() > 0 then
err = err .. " (" .. data:sub(1, 100) .. ")"
end
end
data = result
end
@@ -142,6 +173,64 @@ function HTTP.onDownloadProgress(operationId, url, progress, speed)
end
end
function HTTP.onWsOpen(operationId, message)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if operation.callbacks.onOpen then
operation.callbacks.onOpen(message, operationId)
end
end
function HTTP.onWsMessage(operationId, message)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if operation.callbacks.onMessage then
if operation.json then
local status, result = pcall(function() return json.decode(message) end)
local err = nil
if not status then
err = "JSON ERROR: " .. result
if message and message:len() > 0 then
err = err .. " (" .. message:sub(1, 100) .. ")"
end
end
if err then
if operation.callbacks.onError then
operation.callbacks.onError(err, operationId)
end
else
operation.callbacks.onMessage(result, operationId)
end
else
operation.callbacks.onMessage(message, operationId)
end
end
end
function HTTP.onWsClose(operationId, message)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if operation.callbacks.onClose then
operation.callbacks.onClose(message, operationId)
end
end
function HTTP.onWsError(operationId, message)
local operation = HTTP.operations[operationId]
if operation == nil then
return
end
if operation.callbacks.onError then
operation.callbacks.onError(message, operationId)
end
end
connect(g_http,
{
onGet = HTTP.onGet,
@@ -149,6 +238,10 @@ connect(g_http,
onPost = HTTP.onPost,
onPostProgress = HTTP.onPostProgress,
onDownload = HTTP.onDownload,
onDownloadProgress = HTTP.onDownloadProgress
onDownloadProgress = HTTP.onDownloadProgress,
onWsOpen = HTTP.onWsOpen,
onWsMessage = HTTP.onWsMessage,
onWsClose = HTTP.onWsClose,
onWsError = HTTP.onWsError,
})

View File

@@ -227,6 +227,9 @@ function checkCreatures()
end
local player = g_game.getLocalPlayer()
if not player then
return
end
local dimension = modules.game_interface.getMapPanel():getVisibleDimension()
local spectators = g_map.getSpectatorsInRangeEx(player:getPosition(), false, math.floor(dimension.width / 2), math.floor(dimension.width / 2), math.floor(dimension.height / 2), math.floor(dimension.height / 2))

View File

@@ -1,7 +1,7 @@
MiniWindow
id: botWindow
!text: tr('Bot')
height: 200
height: 600
icon: /images/topbuttons/bot
@onClose: modules.game_bot.onMiniWindowClose()
&save: true
@@ -16,7 +16,7 @@ MiniWindow
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
margin-top: 5
margin-top: 2
margin-right: 90
text-offset: 3 0
@@ -43,7 +43,7 @@ MiniWindow
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
margin-top: 5
margin-top: 3
text-auto-resize: true
!text: tr('Status: waiting')
text-align: center
@@ -53,7 +53,7 @@ MiniWindow
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
margin-top: 3
Panel
anchors.top: prev.bottom
@@ -75,7 +75,7 @@ MiniWindow
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
tab-spacing: 2
tab-spacing: 1
height: 20
movable: false

View File

@@ -10,9 +10,9 @@ botDefaultConfig = {
--#panels
local healTab = addTab("HP")
local attackTab = addTab("Atck")
local warTab = addTab("War")
local batTab = addTab("Batt")
local caveTab = addTab("Cave")
local toolsTab = addTab("Tools")
Panels.TradeMessage()
Panels.AutoStackItems()
@@ -45,12 +45,12 @@ Panels.Equip(healTab)
Panels.Equip(healTab)
Panels.Eating(healTab)
Panels.AttackSpell(attackTab)
Panels.AttackItem(attackTab)
Panels.AttackSpell(batTab)
Panels.AttackItem(batTab)
Panels.AttackLeaderTarget(warTab)
Panels.LimitFloor(warTab)
Panels.AntiPush(warTab)
Panels.AttackLeaderTarget(batTab)
Panels.LimitFloor(batTab)
Panels.AntiPush(batTab)
local waypoints = Panels.Waypoints(caveTab)
local attacking = Panels.Attacking(caveTab)
@@ -61,6 +61,18 @@ end, caveTab)
--#macros
macro(1000, "exchange money", function()
local containers = getContainers()
for i, container in pairs(containers) do
for j, item in ipairs(container:getItems()) do
if item:isStackable() and (item:getId() == 3035 or item:getId() == 3031) and item:getCount() == 100 then
g_game.use(item)
return
end
end
end
end)
macro(1000, "this macro does nothing", "f7", function()
end)

View File

@@ -14,7 +14,7 @@ context.playSound = function(file)
end
botSoundChannel:setEnabled(true)
botSoundChannel:stop(0)
botSoundChannel:play(file, 0, 0)
botSoundChannel:play(file, 0, 1.0)
return botSoundChannel
end

View File

@@ -456,7 +456,7 @@ Panels.Attacking = function(parent)
local ui = context.setupUI([[
Panel
id: attacking
height: 150
height: 140
BotLabel
anchors.top: parent.top
@@ -486,7 +486,7 @@ Panel
anchors.left: parent.left
text: Add
width: 60
height: 20
height: 17
Button
id: edit
@@ -494,7 +494,7 @@ Panel
anchors.horizontalCenter: parent.horizontalCenter
text: Edit
width: 60
height: 20
height: 17
Button
id: remove
@@ -502,7 +502,7 @@ Panel
anchors.right: parent.right
text: Remove
width: 60
height: 20
height: 17
TextList
id: list
@@ -531,7 +531,7 @@ Panel
anchors.left: parent.left
text: Add
width: 60
height: 20
height: 17
Button
id: mEdit
@@ -539,7 +539,7 @@ Panel
anchors.horizontalCenter: parent.horizontalCenter
text: Edit
width: 60
height: 20
height: 17
Button
id: mRemove
@@ -547,7 +547,7 @@ Panel
anchors.right: parent.right
text: Remove
width: 60
height: 20
height: 17
]], parent)
@@ -897,7 +897,10 @@ Panel
if #lootContainers == 0 or not context.storage.looting.enabled then
return false
end
if modules.game_walking.lastManualWalk + 500 > context.now then
return true
end
local pos = context.player:getPosition()
table.sort(lootContainers, function(pos1, pos2)
local dist1 = math.max(math.abs(pos.x-pos1.x), math.abs(pos.y-pos1.y))
@@ -993,7 +996,7 @@ Panel
end
local topItem = tile:getTopUseThing()
if not topItem:isContainer() then
if not topItem or not topItem:isContainer() then
return
end

View File

@@ -15,9 +15,12 @@ Panels.Haste = function(parent)
end
Panels.ManaShield = function(parent)
local lastManaShield = 0
context.macro(100, "Auto Mana Shield", nil, function()
if not context.hasManaShield() then
context.saySpell("utamo vita", 200)
if not context.hasManaShield() or context.now > lastManaShield + 90000 then
if context.saySpell("utamo vita", 200) then
lastManaShield = context.now
end
end
end, parent)
end

View File

@@ -5,7 +5,7 @@ Panels.Looting = function(parent)
local ui = context.setupUI([[
Panel
id: looting
height: 190
height: 180
BotLabel
anchors.top: parent.top
@@ -35,7 +35,7 @@ Panel
anchors.left: parent.left
text: Add
width: 60
height: 20
height: 17
Button
id: edit
@@ -43,7 +43,7 @@ Panel
anchors.horizontalCenter: parent.horizontalCenter
text: Edit
width: 60
height: 20
height: 17
Button
id: remove
@@ -51,7 +51,7 @@ Panel
anchors.right: parent.right
text: Remove
width: 60
height: 20
height: 17
ScrollablePanel
id: items
@@ -90,7 +90,6 @@ Panel
height: 33
margin-top: 2
]], parent)
local lootContainers = { ui.containers.item1, ui.containers.item2, ui.containers.item3, ui.containers.item4, ui.containers.item5 }

View File

@@ -5,7 +5,7 @@ Panels.Waypoints = function(parent)
local ui = context.setupUI([[
Panel
id: waypoints
height: 223
height: 206
BotLabel
anchors.top: parent.top
@@ -35,7 +35,7 @@ Panel
anchors.left: parent.left
text: Add
width: 60
height: 20
height: 17
Button
id: edit
@@ -43,7 +43,7 @@ Panel
anchors.horizontalCenter: parent.horizontalCenter
text: Edit
width: 60
height: 20
height: 17
Button
id: remove
@@ -51,7 +51,7 @@ Panel
anchors.right: parent.right
text: Remove
width: 60
height: 20
height: 17
TextList
id: list
@@ -88,7 +88,7 @@ Panel
text: Goto
width: 61
margin-top: 1
height: 20
height: 17
Button
id: wUse
@@ -96,7 +96,7 @@ Panel
anchors.left: prev.right
text: Use
width: 61
height: 20
height: 17
Button
id: wUseWith
@@ -104,7 +104,7 @@ Panel
anchors.left: prev.right
text: UseWith
width: 61
height: 20
height: 17
Button
id: wWait
@@ -113,7 +113,7 @@ Panel
text: Wait
width: 61
margin-top: 1
height: 20
height: 17
Button
id: wSay
@@ -121,7 +121,7 @@ Panel
anchors.left: prev.right
text: Say
width: 61
height: 20
height: 17
Button
id: wNpc
@@ -129,7 +129,7 @@ Panel
anchors.left: prev.right
text: Say NPC
width: 61
height: 20
height: 17
Button
id: wLabel
@@ -138,7 +138,7 @@ Panel
text: Label
width: 61
margin-top: 1
height: 20
height: 17
Button
id: wFollow
@@ -146,7 +146,7 @@ Panel
anchors.left: prev.right
text: Follow
width: 61
height: 20
height: 17
Button
id: wFunction
@@ -154,7 +154,7 @@ Panel
anchors.left: prev.right
text: Function
width: 61
height: 20
height: 17
BotSwitch
id: recording
@@ -162,7 +162,7 @@ Panel
anchors.left: parent.left
anchors.right: parent.right
text: Auto Recording
height: 20
height: 17
]], parent)

View File

@@ -1,9 +1,10 @@
BotButton < Button
height: 17
margin-top: 2
BotSwitch < Button
margin-top: 2
height: 20
height: 17
image-color: green
$!on:
image-color: red
@@ -17,7 +18,7 @@ SmallBotSwitch < Button
BotLabel < Label
margin-top: 2
height: 20
height: 15
text-auto-resize: true
text-align: center
text-wrap: true

View File

@@ -66,7 +66,7 @@ SingleScrollItemPanel < Panel
step: 1
DualScrollItemPanel < Panel
height: 40
height: 37
margin-top: 2
BotItem
@@ -198,7 +198,7 @@ ItemAndSlotPanel < Panel
height: 20
TwoItemsAndSlotPanel < Panel
height: 40
height: 37
BotItem
id: item1