mirror of
https://github.com/edubart/otclient.git
synced 2025-09-17 16:13:34 +02:00
Compare commits
36 Commits
multi-grap
...
v0.6.3
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b5911cf1de | ||
![]() |
5fbb71157d | ||
![]() |
0ff36a1a0a | ||
![]() |
4a04a18835 | ||
![]() |
6fa9631d6a | ||
![]() |
261642190b | ||
![]() |
95abf2a1d2 | ||
![]() |
c4adf2d817 | ||
![]() |
c7c259ef80 | ||
![]() |
987c6d6c91 | ||
![]() |
c8185474de | ||
![]() |
be071c7103 | ||
![]() |
2f9e2c3e33 | ||
![]() |
b81590f297 | ||
![]() |
e062562888 | ||
![]() |
18d23653c4 | ||
![]() |
6c119627bb | ||
![]() |
d847a78a4d | ||
![]() |
0dccc870b5 | ||
![]() |
e4c7ca604b | ||
![]() |
d427560b98 | ||
![]() |
cc12db0d1f | ||
![]() |
1ce6df99ac | ||
![]() |
57bb6ff974 | ||
![]() |
9bae1b9e25 | ||
![]() |
1415de222c | ||
![]() |
34ceb3c95e | ||
![]() |
b43a196eac | ||
![]() |
a3a65d40ce | ||
![]() |
6ef3508362 | ||
![]() |
a71e07f063 | ||
![]() |
4bdd1e79fd | ||
![]() |
e9e4dcd71b | ||
![]() |
0891e2b30a | ||
![]() |
24664714bd | ||
![]() |
da51dd467e |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,3 @@
|
|||||||
/modules/.project
|
|
||||||
build*
|
build*
|
||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
CMakeFiles
|
CMakeFiles
|
||||||
@@ -39,3 +38,4 @@ tags
|
|||||||
Thumbs.db
|
Thumbs.db
|
||||||
.directory
|
.directory
|
||||||
src/framework/graphics/dx/
|
src/framework/graphics/dx/
|
||||||
|
modules/.project/modules.sublime-workspace
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 2.6)
|
cmake_minimum_required(VERSION 2.6)
|
||||||
project(otclient)
|
project(otclient)
|
||||||
|
|
||||||
set(VERSION "0.6.2")
|
set(VERSION "0.6.3")
|
||||||
|
|
||||||
option(FRAMEWORK_SOUND "Use SOUND " ON)
|
option(FRAMEWORK_SOUND "Use SOUND " ON)
|
||||||
option(FRAMEWORK_GRAPHICS "Use GRAPHICS " ON)
|
option(FRAMEWORK_GRAPHICS "Use GRAPHICS " ON)
|
||||||
|
@@ -11,3 +11,9 @@ HorizontalList < UIScrollArea
|
|||||||
border-width: 1
|
border-width: 1
|
||||||
border-color: #1d222b
|
border-color: #1d222b
|
||||||
background-color: #222833
|
background-color: #222833
|
||||||
|
|
||||||
|
VerticalList < UIScrollArea
|
||||||
|
layout: verticalBox
|
||||||
|
border-width: 1
|
||||||
|
border-color: #1d222b
|
||||||
|
background-color: #222833
|
10
modules/.project/modules.sublime-project
Normal file
10
modules/.project/modules.sublime-project
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"folders":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"path": "..",
|
||||||
|
"folder_exclude_patterns": [".*", "*.*~"],
|
||||||
|
"file_exclude_patterns": [".*", "*.*~"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@@ -104,11 +104,6 @@ function terminate()
|
|||||||
g_settings.set('window-size', g_window.getUnmaximizedSize())
|
g_settings.set('window-size', g_window.getUnmaximizedSize())
|
||||||
g_settings.set('window-pos', g_window.getUnmaximizedPos())
|
g_settings.set('window-pos', g_window.getUnmaximizedPos())
|
||||||
g_settings.set('window-maximized', g_window.isMaximized())
|
g_settings.set('window-maximized', g_window.isMaximized())
|
||||||
|
|
||||||
local protocolVersion = g_game.getProtocolVersion()
|
|
||||||
if protocolVersion ~= 0 then
|
|
||||||
g_settings.set('protocol-version', protocolVersion)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function exit()
|
function exit()
|
||||||
|
@@ -19,4 +19,4 @@ Module
|
|||||||
- client_terminal
|
- client_terminal
|
||||||
- client_modulemanager
|
- client_modulemanager
|
||||||
- client_serverlist
|
- client_serverlist
|
||||||
//- client_stats
|
- client_stats
|
||||||
|
@@ -6,7 +6,7 @@ local enterGame
|
|||||||
local motdWindow
|
local motdWindow
|
||||||
local motdButton
|
local motdButton
|
||||||
local enterGameButton
|
local enterGameButton
|
||||||
local protocolBox
|
local clientBox
|
||||||
local protocolLogin
|
local protocolLogin
|
||||||
local motdEnabled = true
|
local motdEnabled = true
|
||||||
|
|
||||||
@@ -73,11 +73,6 @@ local function onCharacterList(protocol, characters, account, otui)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function onChangeProtocol(combobox, option)
|
|
||||||
local clients = g_game.getSupportedClients(option)
|
|
||||||
protocolBox:setTooltip("Supports Client" .. (#clients > 1 and "s" or "") .. ": " .. table.tostring(clients))
|
|
||||||
end
|
|
||||||
|
|
||||||
local function onUpdateNeeded(protocol, signature)
|
local function onUpdateNeeded(protocol, signature)
|
||||||
loadBox:destroy()
|
loadBox:destroy()
|
||||||
loadBox = nil
|
loadBox = nil
|
||||||
@@ -109,7 +104,8 @@ function EnterGame.init()
|
|||||||
local host = g_settings.get('host')
|
local host = g_settings.get('host')
|
||||||
local port = g_settings.get('port')
|
local port = g_settings.get('port')
|
||||||
local autologin = g_settings.getBoolean('autologin')
|
local autologin = g_settings.getBoolean('autologin')
|
||||||
local protocolVersion = g_settings.getInteger('protocol-version')
|
local clientVersion = g_settings.getInteger('client-version')
|
||||||
|
if clientVersion == 0 then clientVersion = 860 end
|
||||||
|
|
||||||
if port == nil or port == 0 then port = 7171 end
|
if port == nil or port == 0 then port = 7171 end
|
||||||
|
|
||||||
@@ -120,11 +116,11 @@ function EnterGame.init()
|
|||||||
enterGame:getChildById('serverPortTextEdit'):setText(port)
|
enterGame:getChildById('serverPortTextEdit'):setText(port)
|
||||||
enterGame:getChildById('autoLoginBox'):setChecked(autologin)
|
enterGame:getChildById('autoLoginBox'):setChecked(autologin)
|
||||||
|
|
||||||
protocolBox = enterGame:getChildById('protocolComboBox')
|
clientBox = enterGame:getChildById('clientComboBox')
|
||||||
protocolBox.onOptionChange = onChangeProtocol
|
for _, proto in pairs(g_game.getSupportedClients()) do
|
||||||
if protocolVersion then
|
clientBox:addOption(proto)
|
||||||
protocolBox:setCurrentOption(protocolVersion)
|
|
||||||
end
|
end
|
||||||
|
clientBox:setCurrentOption(clientVersion)
|
||||||
|
|
||||||
enterGame:hide()
|
enterGame:hide()
|
||||||
|
|
||||||
@@ -154,7 +150,7 @@ function EnterGame.terminate()
|
|||||||
enterGame = nil
|
enterGame = nil
|
||||||
enterGameButton:destroy()
|
enterGameButton:destroy()
|
||||||
enterGameButton = nil
|
enterGameButton = nil
|
||||||
protocolBox = nil
|
clientBox = nil
|
||||||
if motdWindow then
|
if motdWindow then
|
||||||
motdWindow:destroy()
|
motdWindow:destroy()
|
||||||
motdWindow = nil
|
motdWindow = nil
|
||||||
@@ -218,8 +214,7 @@ function EnterGame.doLogin()
|
|||||||
G.password = enterGame:getChildById('accountPasswordTextEdit'):getText()
|
G.password = enterGame:getChildById('accountPasswordTextEdit'):getText()
|
||||||
G.host = enterGame:getChildById('serverHostTextEdit'):getText()
|
G.host = enterGame:getChildById('serverHostTextEdit'):getText()
|
||||||
G.port = tonumber(enterGame:getChildById('serverPortTextEdit'):getText())
|
G.port = tonumber(enterGame:getChildById('serverPortTextEdit'):getText())
|
||||||
local protocolVersion = tonumber(protocolBox:getText())
|
local clientVersion = tonumber(clientBox:getText())
|
||||||
local clientVersions = g_game.getSupportedClients(protocolVersion)
|
|
||||||
EnterGame.hide()
|
EnterGame.hide()
|
||||||
|
|
||||||
if g_game.isOnline() then
|
if g_game.isOnline() then
|
||||||
@@ -230,6 +225,7 @@ function EnterGame.doLogin()
|
|||||||
|
|
||||||
g_settings.set('host', G.host)
|
g_settings.set('host', G.host)
|
||||||
g_settings.set('port', G.port)
|
g_settings.set('port', G.port)
|
||||||
|
g_settings.set('client-version', clientVersion)
|
||||||
|
|
||||||
protocolLogin = ProtocolLogin.create()
|
protocolLogin = ProtocolLogin.create()
|
||||||
protocolLogin.onLoginError = onError
|
protocolLogin.onLoginError = onError
|
||||||
@@ -245,10 +241,8 @@ function EnterGame.doLogin()
|
|||||||
end })
|
end })
|
||||||
|
|
||||||
g_game.chooseRsa(G.host)
|
g_game.chooseRsa(G.host)
|
||||||
g_game.setProtocolVersion(protocolVersion)
|
g_game.setClientVersion(clientVersion)
|
||||||
if #clientVersions > 0 then
|
g_game.setProtocolVersion(g_game.getProtocolVersionForClient(clientVersion))
|
||||||
g_game.setClientVersion(clientVersions[#clientVersions])
|
|
||||||
end
|
|
||||||
|
|
||||||
if modules.game_things.isLoaded() then
|
if modules.game_things.isLoaded() then
|
||||||
protocolLogin:login(G.host, G.port, G.account, G.password)
|
protocolLogin:login(G.host, G.port, G.account, G.password)
|
||||||
@@ -269,14 +263,14 @@ end
|
|||||||
function EnterGame.setDefaultServer(host, port, protocol)
|
function EnterGame.setDefaultServer(host, port, protocol)
|
||||||
local hostTextEdit = enterGame:getChildById('serverHostTextEdit')
|
local hostTextEdit = enterGame:getChildById('serverHostTextEdit')
|
||||||
local portTextEdit = enterGame:getChildById('serverPortTextEdit')
|
local portTextEdit = enterGame:getChildById('serverPortTextEdit')
|
||||||
local protocolLabel = enterGame:getChildById('protocolLabel')
|
local clientLabel = enterGame:getChildById('clientLabel')
|
||||||
local accountTextEdit = enterGame:getChildById('accountNameTextEdit')
|
local accountTextEdit = enterGame:getChildById('accountNameTextEdit')
|
||||||
local passwordTextEdit = enterGame:getChildById('accountPasswordTextEdit')
|
local passwordTextEdit = enterGame:getChildById('accountPasswordTextEdit')
|
||||||
|
|
||||||
if hostTextEdit:getText() ~= host then
|
if hostTextEdit:getText() ~= host then
|
||||||
hostTextEdit:setText(host)
|
hostTextEdit:setText(host)
|
||||||
portTextEdit:setText(port)
|
portTextEdit:setText(port)
|
||||||
protocolBox:setCurrentOption(protocol)
|
clientBox:setCurrentOption(protocol)
|
||||||
accountTextEdit:setText('')
|
accountTextEdit:setText('')
|
||||||
passwordTextEdit:setText('')
|
passwordTextEdit:setText('')
|
||||||
end
|
end
|
||||||
@@ -292,9 +286,9 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig
|
|||||||
portTextEdit:setVisible(false)
|
portTextEdit:setVisible(false)
|
||||||
portTextEdit:setHeight(0)
|
portTextEdit:setHeight(0)
|
||||||
|
|
||||||
protocolBox:setCurrentOption(protocol)
|
clientBox:setCurrentOption(protocol)
|
||||||
protocolBox:setVisible(false)
|
clientBox:setVisible(false)
|
||||||
protocolBox:setHeight(0)
|
clientBox:setHeight(0)
|
||||||
|
|
||||||
local serverLabel = enterGame:getChildById('serverLabel')
|
local serverLabel = enterGame:getChildById('serverLabel')
|
||||||
serverLabel:setVisible(false)
|
serverLabel:setVisible(false)
|
||||||
@@ -302,9 +296,9 @@ function EnterGame.setUniqueServer(host, port, protocol, windowWidth, windowHeig
|
|||||||
local portLabel = enterGame:getChildById('portLabel')
|
local portLabel = enterGame:getChildById('portLabel')
|
||||||
portLabel:setVisible(false)
|
portLabel:setVisible(false)
|
||||||
portLabel:setHeight(0)
|
portLabel:setHeight(0)
|
||||||
local protocolLabel = enterGame:getChildById('protocolLabel')
|
local clientLabel = enterGame:getChildById('clientLabel')
|
||||||
protocolLabel:setVisible(false)
|
clientLabel:setVisible(false)
|
||||||
protocolLabel:setHeight(0)
|
clientLabel:setHeight(0)
|
||||||
|
|
||||||
local serverListButton = enterGame:getChildById('serverListButton')
|
local serverListButton = enterGame:getChildById('serverListButton')
|
||||||
serverListButton:setVisible(false)
|
serverListButton:setVisible(false)
|
||||||
|
@@ -68,7 +68,7 @@ EnterGameWindow
|
|||||||
|
|
||||||
TextEdit
|
TextEdit
|
||||||
id: serverHostTextEdit
|
id: serverHostTextEdit
|
||||||
!tooltip: tr('Make sure that your client uses\nthe correct game protocol version')
|
!tooltip: tr('Make sure that your client uses\nthe correct game client version')
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: serverListButton.left
|
anchors.right: serverListButton.left
|
||||||
anchors.top: serverLabel.bottom
|
anchors.top: serverLabel.bottom
|
||||||
@@ -76,8 +76,8 @@ EnterGameWindow
|
|||||||
margin-right: 4
|
margin-right: 4
|
||||||
|
|
||||||
MenuLabel
|
MenuLabel
|
||||||
id: protocolLabel
|
id: clientLabel
|
||||||
!text: tr('Protocol')
|
!text: tr('Client Version')
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: serverHostTextEdit.bottom
|
anchors.top: serverHostTextEdit.bottom
|
||||||
text-auto-resize: true
|
text-auto-resize: true
|
||||||
@@ -85,17 +85,13 @@ EnterGameWindow
|
|||||||
margin-top: 8
|
margin-top: 8
|
||||||
|
|
||||||
ComboBox
|
ComboBox
|
||||||
id: protocolComboBox
|
id: clientComboBox
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.horizontalCenter
|
anchors.right: parent.horizontalCenter
|
||||||
anchors.top: protocolLabel.bottom
|
anchors.top: clientLabel.bottom
|
||||||
margin-top: 2
|
margin-top: 2
|
||||||
margin-right: 3
|
margin-right: 3
|
||||||
width: 90
|
width: 90
|
||||||
@onSetup: |
|
|
||||||
for _, proto in pairs(g_game.getSupportedProtocols()) do
|
|
||||||
self:addOption(proto)
|
|
||||||
end
|
|
||||||
|
|
||||||
MenuLabel
|
MenuLabel
|
||||||
id: portLabel
|
id: portLabel
|
||||||
@@ -110,7 +106,7 @@ EnterGameWindow
|
|||||||
text: 7171
|
text: 7171
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.left: parent.horizontalCenter
|
anchors.left: parent.horizontalCenter
|
||||||
anchors.top: protocolComboBox.top
|
anchors.top: clientComboBox.top
|
||||||
margin-left: 3
|
margin-left: 3
|
||||||
|
|
||||||
CheckBox
|
CheckBox
|
||||||
|
@@ -137,7 +137,7 @@ function unloadCurrentModule()
|
|||||||
local module = g_modules.getModule(focusedChild:getText())
|
local module = g_modules.getModule(focusedChild:getText())
|
||||||
if module then
|
if module then
|
||||||
module:unload()
|
module:unload()
|
||||||
if ModuleManager == nil then return end
|
if modules.client_modulemanager == nil then return end
|
||||||
updateModuleInfo(module:getName())
|
updateModuleInfo(module:getName())
|
||||||
refreshLoadedModules()
|
refreshLoadedModules()
|
||||||
end
|
end
|
||||||
|
@@ -49,7 +49,7 @@ MainWindow
|
|||||||
anchors.left: protocolLabel.left
|
anchors.left: protocolLabel.left
|
||||||
anchors.right: port.right
|
anchors.right: port.right
|
||||||
@onSetup: |
|
@onSetup: |
|
||||||
for _, proto in pairs(g_game.getSupportedProtocols()) do
|
for _, proto in pairs(g_game.getSupportedClients()) do
|
||||||
self:addOption(proto)
|
self:addOption(proto)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@ -257,10 +257,13 @@ function flushLines()
|
|||||||
for _,line in pairs(cachedLines) do
|
for _,line in pairs(cachedLines) do
|
||||||
-- delete old lines if needed
|
-- delete old lines if needed
|
||||||
if numLines > MaxLogLines then
|
if numLines > MaxLogLines then
|
||||||
local len = #terminalBuffer:getChildByIndex(1):getText()
|
local firstChild = terminalBuffer:getChildByIndex(1)
|
||||||
terminalBuffer:getChildByIndex(1):destroy()
|
if firstChild then
|
||||||
table.remove(allLines, 1)
|
local len = #firstChild:getText()
|
||||||
fulltext = string.sub(fulltext, len)
|
firstChild:destroy()
|
||||||
|
table.remove(allLines, 1)
|
||||||
|
fulltext = string.sub(fulltext, len)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local label = g_ui.createWidget('TerminalLabel', terminalBuffer)
|
local label = g_ui.createWidget('TerminalLabel', terminalBuffer)
|
||||||
@@ -285,6 +288,7 @@ function addLine(text, color)
|
|||||||
flushEvent = scheduleEvent(flushLines, 10)
|
flushEvent = scheduleEvent(flushLines, 10)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
text = string.gsub(text, '\t', ' ')
|
||||||
table.insert(cachedLines, {text=text, color=color})
|
table.insert(cachedLines, {text=text, color=color})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@ -20,8 +20,8 @@ function string:starts(start)
|
|||||||
return string.sub(self, 1, #start) == start
|
return string.sub(self, 1, #start) == start
|
||||||
end
|
end
|
||||||
|
|
||||||
function string.ends(s, test)
|
function string:ends(test)
|
||||||
return test =='' or string.sub(s,-string.len(test)) == test
|
return test =='' or string.sub(self,-string.len(test)) == test
|
||||||
end
|
end
|
||||||
|
|
||||||
function string:trim()
|
function string:trim()
|
||||||
|
@@ -110,7 +110,9 @@ function UITabBar:selectTab(tab)
|
|||||||
tab:setOn(false)
|
tab:setOn(false)
|
||||||
|
|
||||||
local parent = tab:getParent()
|
local parent = tab:getParent()
|
||||||
parent:focusChild(tab, MouseFocusReason)
|
if parent then
|
||||||
|
parent:focusChild(tab, MouseFocusReason)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function UITabBar:selectNextTab()
|
function UITabBar:selectNextTab()
|
||||||
|
@@ -1,11 +1,16 @@
|
|||||||
battleWindow = nil
|
battleWindow = nil
|
||||||
battleButton = nil
|
battleButton = nil
|
||||||
battlePanel = nil
|
battlePanel = nil
|
||||||
|
filterPanel = nil
|
||||||
|
toggleFilterButton = nil
|
||||||
lastBattleButtonSwitched = nil
|
lastBattleButtonSwitched = nil
|
||||||
battleButtonsByCreaturesList = {}
|
battleButtonsByCreaturesList = {}
|
||||||
|
creatureAgeList = {}
|
||||||
|
|
||||||
mouseWidget = nil
|
mouseWidget = nil
|
||||||
|
|
||||||
|
sortTypeBox = nil
|
||||||
|
sortOrderBox = nil
|
||||||
hidePlayersButton = nil
|
hidePlayersButton = nil
|
||||||
hideNPCsButton = nil
|
hideNPCsButton = nil
|
||||||
hideMonstersButton = nil
|
hideMonstersButton = nil
|
||||||
@@ -25,6 +30,15 @@ function init()
|
|||||||
|
|
||||||
battlePanel = battleWindow:recursiveGetChildById('battlePanel')
|
battlePanel = battleWindow:recursiveGetChildById('battlePanel')
|
||||||
|
|
||||||
|
filterPanel = battleWindow:recursiveGetChildById('filterPanel')
|
||||||
|
toggleFilterButton = battleWindow:recursiveGetChildById('toggleFilterButton')
|
||||||
|
|
||||||
|
if isHidingFilters() then
|
||||||
|
hideFilterPanel()
|
||||||
|
end
|
||||||
|
|
||||||
|
sortTypeBox = battleWindow:recursiveGetChildById('sortTypeBox')
|
||||||
|
sortOrderBox = battleWindow:recursiveGetChildById('sortOrderBox')
|
||||||
hidePlayersButton = battleWindow:recursiveGetChildById('hidePlayers')
|
hidePlayersButton = battleWindow:recursiveGetChildById('hidePlayers')
|
||||||
hideNPCsButton = battleWindow:recursiveGetChildById('hideNPCs')
|
hideNPCsButton = battleWindow:recursiveGetChildById('hideNPCs')
|
||||||
hideMonstersButton = battleWindow:recursiveGetChildById('hideMonsters')
|
hideMonstersButton = battleWindow:recursiveGetChildById('hideMonsters')
|
||||||
@@ -38,6 +52,18 @@ function init()
|
|||||||
|
|
||||||
battleWindow:setContentMinimumHeight(80)
|
battleWindow:setContentMinimumHeight(80)
|
||||||
|
|
||||||
|
sortTypeBox:addOption('Name', 'name')
|
||||||
|
sortTypeBox:addOption('Distance', 'distance')
|
||||||
|
sortTypeBox:addOption('Age', 'age')
|
||||||
|
sortTypeBox:addOption('Health', 'health')
|
||||||
|
sortTypeBox:setCurrentOptionByData(getSortType())
|
||||||
|
sortTypeBox.onOptionChange = onChangeSortType
|
||||||
|
|
||||||
|
sortOrderBox:addOption('Asc.', 'asc')
|
||||||
|
sortOrderBox:addOption('Desc.', 'desc')
|
||||||
|
sortOrderBox:setCurrentOptionByData(getSortOrder())
|
||||||
|
sortOrderBox.onOptionChange = onChangeSortOrder
|
||||||
|
|
||||||
connect(Creature, {
|
connect(Creature, {
|
||||||
onSkullChange = updateCreatureSkull,
|
onSkullChange = updateCreatureSkull,
|
||||||
onEmblemChange = updateCreatureEmblem,
|
onEmblemChange = updateCreatureEmblem,
|
||||||
@@ -47,6 +73,10 @@ function init()
|
|||||||
onAppear = onCreatureAppear,
|
onAppear = onCreatureAppear,
|
||||||
onDisappear = onCreatureDisappear
|
onDisappear = onCreatureDisappear
|
||||||
})
|
})
|
||||||
|
|
||||||
|
connect(LocalPlayer, {
|
||||||
|
onPositionChange = onCreaturePositionChange
|
||||||
|
})
|
||||||
|
|
||||||
connect(g_game, {
|
connect(g_game, {
|
||||||
onAttackingCreatureChange = onAttack,
|
onAttackingCreatureChange = onAttack,
|
||||||
@@ -75,6 +105,10 @@ function terminate()
|
|||||||
onDisappear = onCreatureDisappear
|
onDisappear = onCreatureDisappear
|
||||||
})
|
})
|
||||||
|
|
||||||
|
disconnect(LocalPlayer, {
|
||||||
|
onPositionChange = onCreaturePositionChange
|
||||||
|
})
|
||||||
|
|
||||||
disconnect(g_game, {
|
disconnect(g_game, {
|
||||||
onAttackingCreatureChange = onAttack,
|
onAttackingCreatureChange = onAttack,
|
||||||
onFollowingCreatureChange = onFollow,
|
onFollowingCreatureChange = onFollow,
|
||||||
@@ -96,6 +130,93 @@ function onMiniWindowClose()
|
|||||||
battleButton:setOn(false)
|
battleButton:setOn(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function getSortType()
|
||||||
|
local settings = g_settings.getNode('BattleList')
|
||||||
|
if not settings then
|
||||||
|
return 'name'
|
||||||
|
end
|
||||||
|
return settings['sortType']
|
||||||
|
end
|
||||||
|
|
||||||
|
function setSortType(state)
|
||||||
|
settings = {}
|
||||||
|
settings['sortType'] = state
|
||||||
|
g_settings.mergeNode('BattleList', settings)
|
||||||
|
|
||||||
|
checkCreatures()
|
||||||
|
end
|
||||||
|
|
||||||
|
function getSortOrder()
|
||||||
|
local settings = g_settings.getNode('BattleList')
|
||||||
|
if not settings then
|
||||||
|
return 'asc'
|
||||||
|
end
|
||||||
|
return settings['sortOrder']
|
||||||
|
end
|
||||||
|
|
||||||
|
function setSortOrder(state)
|
||||||
|
settings = {}
|
||||||
|
settings['sortOrder'] = state
|
||||||
|
g_settings.mergeNode('BattleList', settings)
|
||||||
|
|
||||||
|
checkCreatures()
|
||||||
|
end
|
||||||
|
|
||||||
|
function isSortAsc()
|
||||||
|
return getSortOrder() == 'asc'
|
||||||
|
end
|
||||||
|
|
||||||
|
function isSortDesc()
|
||||||
|
return getSortOrder() == 'desc'
|
||||||
|
end
|
||||||
|
|
||||||
|
function isHidingFilters()
|
||||||
|
local settings = g_settings.getNode('BattleList')
|
||||||
|
if not settings then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return settings['hidingFilters']
|
||||||
|
end
|
||||||
|
|
||||||
|
function setHidingFilters(state)
|
||||||
|
settings = {}
|
||||||
|
settings['hidingFilters'] = state
|
||||||
|
g_settings.mergeNode('BattleList', settings)
|
||||||
|
end
|
||||||
|
|
||||||
|
function hideFilterPanel()
|
||||||
|
filterPanel.originalHeight = filterPanel:getHeight()
|
||||||
|
filterPanel:setHeight(0)
|
||||||
|
toggleFilterButton:getParent():setMarginTop(0)
|
||||||
|
toggleFilterButton:setImageClip(torect("0 0 21 12"))
|
||||||
|
setHidingFilters(true)
|
||||||
|
filterPanel:setVisible(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
function showFilterPanel()
|
||||||
|
toggleFilterButton:getParent():setMarginTop(5)
|
||||||
|
filterPanel:setHeight(filterPanel.originalHeight)
|
||||||
|
toggleFilterButton:setImageClip(torect("21 0 21 12"))
|
||||||
|
setHidingFilters(false)
|
||||||
|
filterPanel:setVisible(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
function toggleFilterPanel()
|
||||||
|
if filterPanel:isVisible() then
|
||||||
|
hideFilterPanel()
|
||||||
|
else
|
||||||
|
showFilterPanel()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function onChangeSortType(comboBox, option)
|
||||||
|
setSortType(option:lower())
|
||||||
|
end
|
||||||
|
|
||||||
|
function onChangeSortOrder(comboBox, option)
|
||||||
|
setSortOrder(option:lower():gsub('[.]', '')) -- Replace dot in option name
|
||||||
|
end
|
||||||
|
|
||||||
function checkCreatures()
|
function checkCreatures()
|
||||||
removeAllCreatures()
|
removeAllCreatures()
|
||||||
|
|
||||||
@@ -151,15 +272,42 @@ end
|
|||||||
function onCreatureHealthPercentChange(creature, health)
|
function onCreatureHealthPercentChange(creature, health)
|
||||||
local battleButton = battleButtonsByCreaturesList[creature:getId()]
|
local battleButton = battleButtonsByCreaturesList[creature:getId()]
|
||||||
if battleButton then
|
if battleButton then
|
||||||
|
if getSortType() == 'health' then
|
||||||
|
removeCreature(creature)
|
||||||
|
addCreature(creature)
|
||||||
|
return
|
||||||
|
end
|
||||||
battleButton:setLifeBarPercent(creature:getHealthPercent())
|
battleButton:setLifeBarPercent(creature:getHealthPercent())
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function getDistanceBetween(p1, p2)
|
||||||
|
return math.max(math.abs(p1.x - p2.x), math.abs(p1.y - p2.y))
|
||||||
|
end
|
||||||
|
|
||||||
function onCreaturePositionChange(creature, newPos, oldPos)
|
function onCreaturePositionChange(creature, newPos, oldPos)
|
||||||
if creature:isLocalPlayer() then
|
if creature:isLocalPlayer() then
|
||||||
if oldPos and newPos and newPos.z ~= oldPos.z then
|
if oldPos and newPos and newPos.z ~= oldPos.z then
|
||||||
checkCreatures()
|
checkCreatures()
|
||||||
else
|
else
|
||||||
|
-- Distance will change when moving, recalculate and move to correct index
|
||||||
|
if getSortType() == 'distance' then
|
||||||
|
local distanceList = {}
|
||||||
|
for id, creatureButton in pairs(battleButtonsByCreaturesList) do
|
||||||
|
table.insert(distanceList, {distance = getDistanceBetween(newPos, creatureButton.creature:getPosition()), widget = creatureButton})
|
||||||
|
end
|
||||||
|
|
||||||
|
if isSortAsc() then
|
||||||
|
table.sort(distanceList, function(a, b) return a.distance < b.distance end)
|
||||||
|
else
|
||||||
|
table.sort(distanceList, function(a, b) return a.distance > b.distance end)
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1, #distanceList do
|
||||||
|
battlePanel:moveChildToIndex(distanceList[i].widget, i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
for id, creatureButton in pairs(battleButtonsByCreaturesList) do
|
for id, creatureButton in pairs(battleButtonsByCreaturesList) do
|
||||||
addCreature(creatureButton.creature)
|
addCreature(creatureButton.creature)
|
||||||
end
|
end
|
||||||
@@ -170,6 +318,9 @@ function onCreaturePositionChange(creature, newPos, oldPos)
|
|||||||
if has and not fit then
|
if has and not fit then
|
||||||
removeCreature(creature)
|
removeCreature(creature)
|
||||||
elseif fit then
|
elseif fit then
|
||||||
|
if has and getSortType() == 'distance' then
|
||||||
|
removeCreature(creature)
|
||||||
|
end
|
||||||
addCreature(creature)
|
addCreature(creature)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -201,8 +352,13 @@ function addCreature(creature)
|
|||||||
local creatureId = creature:getId()
|
local creatureId = creature:getId()
|
||||||
local battleButton = battleButtonsByCreaturesList[creatureId]
|
local battleButton = battleButtonsByCreaturesList[creatureId]
|
||||||
|
|
||||||
|
-- Register when creature is added to battlelist for the first time
|
||||||
|
if not creatureAgeList[creatureId] then
|
||||||
|
creatureAgeList[creatureId] = os.time()
|
||||||
|
end
|
||||||
|
|
||||||
if not battleButton then
|
if not battleButton then
|
||||||
battleButton = g_ui.createWidget('BattleButton', battlePanel)
|
battleButton = g_ui.createWidget('BattleButton')
|
||||||
battleButton:setup(creature)
|
battleButton:setup(creature)
|
||||||
|
|
||||||
battleButton.onHoverChange = onBattleButtonHoverChange
|
battleButton.onHoverChange = onBattleButtonHoverChange
|
||||||
@@ -217,6 +373,77 @@ function addCreature(creature)
|
|||||||
if creature == g_game.getFollowingCreature() then
|
if creature == g_game.getFollowingCreature() then
|
||||||
onFollow(creature)
|
onFollow(creature)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local inserted = false
|
||||||
|
local nameLower = creature:getName():lower()
|
||||||
|
local healthPercent = creature:getHealthPercent()
|
||||||
|
local playerPosition = g_game.getLocalPlayer():getPosition()
|
||||||
|
local distance = getDistanceBetween(playerPosition, creature:getPosition())
|
||||||
|
local age = creatureAgeList[creatureId]
|
||||||
|
|
||||||
|
local childCount = battlePanel:getChildCount()
|
||||||
|
for i = 1, childCount do
|
||||||
|
local child = battlePanel:getChildByIndex(i)
|
||||||
|
local childName = child:getCreature():getName():lower()
|
||||||
|
local equal = false
|
||||||
|
if getSortType() == 'age' then
|
||||||
|
local childAge = creatureAgeList[child:getCreature():getId()]
|
||||||
|
if (age < childAge and isSortAsc()) or (age > childAge and isSortDesc()) then
|
||||||
|
battlePanel:insertChild(i, battleButton)
|
||||||
|
inserted = true
|
||||||
|
break
|
||||||
|
elseif age == childAge then
|
||||||
|
equal = true
|
||||||
|
end
|
||||||
|
elseif getSortType() == 'distance' then
|
||||||
|
local childDistance = getDistanceBetween(child:getCreature():getPosition(), playerPosition)
|
||||||
|
if (distance < childDistance and isSortAsc()) or (distance > childDistance and isSortDesc()) then
|
||||||
|
battlePanel:insertChild(i, battleButton)
|
||||||
|
inserted = true
|
||||||
|
break
|
||||||
|
elseif childDistance == distance then
|
||||||
|
equal = true
|
||||||
|
end
|
||||||
|
elseif getSortType() == 'health' then
|
||||||
|
local childHealth = child:getCreature():getHealthPercent()
|
||||||
|
if (healthPercent < childHealth and isSortAsc()) or (healthPercent > childHealth and isSortDesc()) then
|
||||||
|
battlePanel:insertChild(i, battleButton)
|
||||||
|
inserted = true
|
||||||
|
break
|
||||||
|
elseif healthPercent == childHealth then
|
||||||
|
equal = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If any other sort type is selected and values are equal, sort it by name also
|
||||||
|
if getSortType() == 'name' or equal then
|
||||||
|
local length = math.min(childName:len(), nameLower:len())
|
||||||
|
for j=1,length do
|
||||||
|
if (nameLower:byte(j) < childName:byte(j) and isSortAsc()) or (nameLower:byte(j) > childName:byte(j) and isSortDesc()) then
|
||||||
|
battlePanel:insertChild(i, battleButton)
|
||||||
|
inserted = true
|
||||||
|
break
|
||||||
|
elseif (nameLower:byte(j) > childName:byte(j) and isSortAsc()) or (nameLower:byte(j) < childName:byte(j) and isSortDesc()) then
|
||||||
|
break
|
||||||
|
elseif j == nameLower:len() and isSortAsc() then
|
||||||
|
battlePanel:insertChild(i, battleButton)
|
||||||
|
inserted = true
|
||||||
|
elseif j == childName:len() and isSortDesc() then
|
||||||
|
battlePanel:insertChild(i, battleButton)
|
||||||
|
inserted = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if inserted then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Insert at the end if no other place is found
|
||||||
|
if not inserted then
|
||||||
|
battlePanel:insertChild(childCount + 1, battleButton)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
battleButton:setLifeBarPercent(creature:getHealthPercent())
|
battleButton:setLifeBarPercent(creature:getHealthPercent())
|
||||||
end
|
end
|
||||||
@@ -226,6 +453,7 @@ function addCreature(creature)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function removeAllCreatures()
|
function removeAllCreatures()
|
||||||
|
creatureAgeList = {}
|
||||||
for i, v in pairs(battleButtonsByCreaturesList) do
|
for i, v in pairs(battleButtonsByCreaturesList) do
|
||||||
removeCreature(v.creature)
|
removeCreature(v.creature)
|
||||||
end
|
end
|
||||||
|
@@ -45,11 +45,12 @@ MiniWindow
|
|||||||
&save: true
|
&save: true
|
||||||
|
|
||||||
Panel
|
Panel
|
||||||
|
id: filterPanel
|
||||||
margin-top: 26
|
margin-top: 26
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: miniwindowScrollBar.left
|
anchors.right: miniwindowScrollBar.left
|
||||||
height: 20
|
height: 45
|
||||||
|
|
||||||
Panel
|
Panel
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
@@ -85,16 +86,56 @@ MiniWindow
|
|||||||
!tooltip: tr('Hide party members')
|
!tooltip: tr('Hide party members')
|
||||||
@onCheckChange: modules.game_battle.checkCreatures()
|
@onCheckChange: modules.game_battle.checkCreatures()
|
||||||
|
|
||||||
HorizontalSeparator
|
Panel
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
height: 20
|
||||||
|
width: 128
|
||||||
|
margin-top: 6
|
||||||
|
|
||||||
|
ComboBox
|
||||||
|
id: sortTypeBox
|
||||||
|
width: 74
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: prev.right
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
margin-left: -28
|
||||||
|
|
||||||
|
ComboBox
|
||||||
|
id: sortOrderBox
|
||||||
|
width: 54
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: prev.right
|
||||||
|
margin-left: 4
|
||||||
|
|
||||||
|
Panel
|
||||||
|
height: 18
|
||||||
anchors.top: prev.bottom
|
anchors.top: prev.bottom
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: miniwindowScrollBar.left
|
anchors.right: miniwindowScrollBar.left
|
||||||
margin-right: 1
|
margin-top: 5
|
||||||
margin-top: 4
|
|
||||||
|
|
||||||
|
UIWidget
|
||||||
|
id: toggleFilterButton
|
||||||
|
anchors.top: prev.top
|
||||||
|
width: 21
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
image-source: /images/ui/arrow_vertical
|
||||||
|
image-rect: 0 0 21 12
|
||||||
|
image-clip: 21 0 21 12
|
||||||
|
@onClick: modules.game_battle.toggleFilterPanel()
|
||||||
|
phantom: false
|
||||||
|
|
||||||
|
HorizontalSeparator
|
||||||
|
anchors.top: prev.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: miniwindowScrollBar.left
|
||||||
|
margin-right: 1
|
||||||
|
margin-top: 11
|
||||||
|
|
||||||
MiniWindowContents
|
MiniWindowContents
|
||||||
anchors.top: prev.bottom
|
anchors.top: prev.bottom
|
||||||
margin-top: 0
|
margin-top: 6
|
||||||
|
|
||||||
Panel
|
Panel
|
||||||
id: battlePanel
|
id: battlePanel
|
||||||
|
206
modules/game_console/communicationwindow.otui
Normal file
206
modules/game_console/communicationwindow.otui
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
IgnoreListLabel < Label
|
||||||
|
font: verdana-11px-monochrome
|
||||||
|
background-color: alpha
|
||||||
|
text-offset: 2 0
|
||||||
|
focusable: true
|
||||||
|
phantom: false
|
||||||
|
|
||||||
|
$focus:
|
||||||
|
background-color: #ffffff22
|
||||||
|
color: #ffffff
|
||||||
|
|
||||||
|
WhiteListLabel < Label
|
||||||
|
font: verdana-11px-monochrome
|
||||||
|
background-color: alpha
|
||||||
|
text-offset: 2 0
|
||||||
|
focusable: true
|
||||||
|
phantom: false
|
||||||
|
|
||||||
|
$focus:
|
||||||
|
background-color: #ffffff22
|
||||||
|
color: #ffffff
|
||||||
|
|
||||||
|
|
||||||
|
MainWindow
|
||||||
|
id: communicationWindow
|
||||||
|
!text: tr('Ignore List')
|
||||||
|
size: 515 410
|
||||||
|
@onEscape: self:destroy()
|
||||||
|
|
||||||
|
CheckBox
|
||||||
|
id: checkboxUseIgnoreList
|
||||||
|
!text: tr('Activate ignorelist')
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
width: 180
|
||||||
|
|
||||||
|
Label
|
||||||
|
!text: tr('Ignored Players:')
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
margin-top: 10
|
||||||
|
|
||||||
|
TextList
|
||||||
|
id: ignoreList
|
||||||
|
vertical-scrollbar: ignoreListScrollBar
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
height: 150
|
||||||
|
width: 230
|
||||||
|
margin-bottom: 10
|
||||||
|
margin-top: 3
|
||||||
|
padding: 1
|
||||||
|
focusable: false
|
||||||
|
|
||||||
|
TextEdit
|
||||||
|
id: ignoreNameEdit
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
width: 110
|
||||||
|
margin-top: 5
|
||||||
|
|
||||||
|
Button
|
||||||
|
id: buttonIgnoreAdd
|
||||||
|
!text: tr('Add')
|
||||||
|
width: 48
|
||||||
|
height: 20
|
||||||
|
margin-left: 5
|
||||||
|
anchors.top: prev.top
|
||||||
|
anchors.left: prev.right
|
||||||
|
|
||||||
|
Button
|
||||||
|
id: buttonIgnoreRemove
|
||||||
|
!text: tr('Remove')
|
||||||
|
width: 64
|
||||||
|
height: 20
|
||||||
|
margin-left: 5
|
||||||
|
anchors.top: prev.top
|
||||||
|
anchors.left: prev.right
|
||||||
|
|
||||||
|
Label
|
||||||
|
!text: tr('Global ignore settings')
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
margin-top: 20
|
||||||
|
|
||||||
|
CheckBox
|
||||||
|
id: checkboxIgnorePrivateMessages
|
||||||
|
!text: tr('Ignore Private Messages')
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
width: 180
|
||||||
|
margin-top: 5
|
||||||
|
|
||||||
|
CheckBox
|
||||||
|
id: checkboxIgnoreYelling
|
||||||
|
!text: tr('Ignore Yelling')
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
width: 180
|
||||||
|
margin-top: 5
|
||||||
|
|
||||||
|
CheckBox
|
||||||
|
id: checkboxUseWhiteList
|
||||||
|
!text: tr('Activate whitelist')
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: ignoreList.right
|
||||||
|
margin-left: 20
|
||||||
|
width: 180
|
||||||
|
|
||||||
|
Label
|
||||||
|
!text: tr('Allowed Players:')
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
anchors.left: prev.left
|
||||||
|
margin-top: 10
|
||||||
|
|
||||||
|
TextList
|
||||||
|
id: whiteList
|
||||||
|
vertical-scrollbar: whiteListScrollBar
|
||||||
|
anchors.left: prev.left
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
height: 150
|
||||||
|
width: 230
|
||||||
|
margin-bottom: 10
|
||||||
|
margin-top: 3
|
||||||
|
padding: 1
|
||||||
|
focusable: false
|
||||||
|
|
||||||
|
TextEdit
|
||||||
|
id: whitelistNameEdit
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
anchors.left: prev.left
|
||||||
|
width: 110
|
||||||
|
margin-top: 5
|
||||||
|
|
||||||
|
Button
|
||||||
|
id: buttonWhitelistAdd
|
||||||
|
!text: tr('Add')
|
||||||
|
width: 48
|
||||||
|
height: 20
|
||||||
|
margin-left: 5
|
||||||
|
anchors.top: prev.top
|
||||||
|
anchors.left: prev.right
|
||||||
|
|
||||||
|
Button
|
||||||
|
id: buttonWhitelistRemove
|
||||||
|
!text: tr('Remove')
|
||||||
|
width: 64
|
||||||
|
height: 20
|
||||||
|
margin-left: 5
|
||||||
|
anchors.top: prev.top
|
||||||
|
anchors.left: prev.right
|
||||||
|
|
||||||
|
Label
|
||||||
|
!text: tr('Global whitelist settings')
|
||||||
|
anchors.left: whiteList.left
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
margin-top: 20
|
||||||
|
|
||||||
|
CheckBox
|
||||||
|
id: checkboxAllowVIPs
|
||||||
|
!text: tr('Allow VIPs to message you')
|
||||||
|
anchors.left: prev.left
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
width: 180
|
||||||
|
margin-top: 5
|
||||||
|
|
||||||
|
Panel
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
height: 30
|
||||||
|
|
||||||
|
Panel
|
||||||
|
size: 160 30
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
|
Button
|
||||||
|
id: buttonSave
|
||||||
|
!text: tr('Save')
|
||||||
|
width: 75
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
|
||||||
|
Button
|
||||||
|
id: buttonCancel
|
||||||
|
!text: tr('Cancel')
|
||||||
|
width: 75
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: prev.right
|
||||||
|
margin-left: 10
|
||||||
|
|
||||||
|
VerticalScrollBar
|
||||||
|
id: ignoreListScrollBar
|
||||||
|
anchors.top: ignoreList.top
|
||||||
|
anchors.bottom: ignoreList.bottom
|
||||||
|
anchors.right: ignoreList.right
|
||||||
|
step: 14
|
||||||
|
pixels-scroll: true
|
||||||
|
|
||||||
|
VerticalScrollBar
|
||||||
|
id: whiteListScrollBar
|
||||||
|
anchors.top: whiteList.top
|
||||||
|
anchors.bottom: whiteList.bottom
|
||||||
|
anchors.right: whiteList.right
|
||||||
|
step: 14
|
||||||
|
pixels-scroll: true
|
@@ -61,7 +61,7 @@ consoleTabBar = nil
|
|||||||
consoleTextEdit = nil
|
consoleTextEdit = nil
|
||||||
channels = nil
|
channels = nil
|
||||||
channelsWindow = nil
|
channelsWindow = nil
|
||||||
ignoreWindow = nil
|
communicationWindow = nil
|
||||||
ownPrivateName = nil
|
ownPrivateName = nil
|
||||||
messageHistory = {}
|
messageHistory = {}
|
||||||
currentMessageIndex = 0
|
currentMessageIndex = 0
|
||||||
@@ -74,10 +74,14 @@ violationReportTab = nil
|
|||||||
ignoredChannels = {}
|
ignoredChannels = {}
|
||||||
filters = {}
|
filters = {}
|
||||||
|
|
||||||
local ignoreSettings = {
|
local communicationSettings = {
|
||||||
|
useIgnoreList = true,
|
||||||
|
useWhiteList = true,
|
||||||
privateMessages = false,
|
privateMessages = false,
|
||||||
yelling = false,
|
yelling = false,
|
||||||
players = {}
|
allowVIPs = false,
|
||||||
|
ignoredPlayers = {},
|
||||||
|
whitelistedPlayers = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
function init()
|
function init()
|
||||||
@@ -139,10 +143,59 @@ function init()
|
|||||||
g_keyboard.bindKeyDown('Ctrl+O', g_game.requestChannels)
|
g_keyboard.bindKeyDown('Ctrl+O', g_game.requestChannels)
|
||||||
g_keyboard.bindKeyDown('Ctrl+E', removeCurrentTab)
|
g_keyboard.bindKeyDown('Ctrl+E', removeCurrentTab)
|
||||||
g_keyboard.bindKeyDown('Ctrl+H', openHelp)
|
g_keyboard.bindKeyDown('Ctrl+H', openHelp)
|
||||||
|
|
||||||
|
consoleToggleChat = consolePanel:getChildById('toggleChat')
|
||||||
load()
|
load()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function toggleChat()
|
||||||
|
if consoleToggleChat:isChecked() then
|
||||||
|
disableChat()
|
||||||
|
else
|
||||||
|
enableChat()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function enableChat()
|
||||||
|
local gameInterface = modules.game_interface
|
||||||
|
|
||||||
|
consoleTextEdit:setVisible(true)
|
||||||
|
consoleTextEdit:setText("")
|
||||||
|
|
||||||
|
g_keyboard.unbindKeyUp("Space")
|
||||||
|
g_keyboard.unbindKeyUp("Enter")
|
||||||
|
|
||||||
|
gameInterface.unbindWalkKey("W")
|
||||||
|
gameInterface.unbindWalkKey("D")
|
||||||
|
gameInterface.unbindWalkKey("S")
|
||||||
|
gameInterface.unbindWalkKey("A")
|
||||||
|
|
||||||
|
consoleToggleChat:setTooltip(tr("Disable chat mode, allow to walk using ASDW"))
|
||||||
|
end
|
||||||
|
|
||||||
|
function disableChat()
|
||||||
|
local gameInterface = modules.game_interface
|
||||||
|
|
||||||
|
consoleTextEdit:setVisible(false)
|
||||||
|
consoleTextEdit:setText("")
|
||||||
|
|
||||||
|
local quickFunc = function()
|
||||||
|
if consoleToggleChat:isChecked() then
|
||||||
|
consoleToggleChat:setChecked(false)
|
||||||
|
end
|
||||||
|
enableChat()
|
||||||
|
end
|
||||||
|
g_keyboard.bindKeyUp("Space", quickFunc)
|
||||||
|
g_keyboard.bindKeyUp("Enter", quickFunc)
|
||||||
|
|
||||||
|
gameInterface.bindWalkKey("W", North)
|
||||||
|
gameInterface.bindWalkKey("D", East)
|
||||||
|
gameInterface.bindWalkKey("S", South)
|
||||||
|
gameInterface.bindWalkKey("A", West)
|
||||||
|
|
||||||
|
consoleToggleChat:setTooltip(tr("Enable chat mode"))
|
||||||
|
end
|
||||||
|
|
||||||
function terminate()
|
function terminate()
|
||||||
save()
|
save()
|
||||||
disconnect(g_game, {
|
disconnect(g_game, {
|
||||||
@@ -166,14 +219,14 @@ function terminate()
|
|||||||
g_keyboard.unbindKeyDown('Ctrl+E')
|
g_keyboard.unbindKeyDown('Ctrl+E')
|
||||||
g_keyboard.unbindKeyDown('Ctrl+H')
|
g_keyboard.unbindKeyDown('Ctrl+H')
|
||||||
|
|
||||||
saveIgnoreSettings()
|
saveCommunicationSettings()
|
||||||
|
|
||||||
if channelsWindow then
|
if channelsWindow then
|
||||||
channelsWindow:destroy()
|
channelsWindow:destroy()
|
||||||
end
|
end
|
||||||
|
|
||||||
if ignoreWindow then
|
if communicationWindow then
|
||||||
ignoreWindow:destroy()
|
communicationWindow:destroy()
|
||||||
end
|
end
|
||||||
|
|
||||||
if violationWindow then
|
if violationWindow then
|
||||||
@@ -197,7 +250,7 @@ function load()
|
|||||||
if settings then
|
if settings then
|
||||||
messageHistory = settings.messageHistory or {}
|
messageHistory = settings.messageHistory or {}
|
||||||
end
|
end
|
||||||
loadIgnoreSettings()
|
loadCommunicationSettings()
|
||||||
end
|
end
|
||||||
|
|
||||||
function onTabChange(tabBar, tab)
|
function onTabChange(tabBar, tab)
|
||||||
@@ -466,7 +519,7 @@ function addTabText(text, speaktype, tab, creatureName)
|
|||||||
-- Remove the curly braces
|
-- Remove the curly braces
|
||||||
for i = 1, #highlightData / 3 do
|
for i = 1, #highlightData / 3 do
|
||||||
local dataBlock = { _start = highlightData[(i-1)*3+1], _end = highlightData[(i-1)*3+2], words = highlightData[(i-1)*3+3] }
|
local dataBlock = { _start = highlightData[(i-1)*3+1], _end = highlightData[(i-1)*3+2], words = highlightData[(i-1)*3+3] }
|
||||||
text = text:gsub("{"..dataBlock.words.."}", dataBlock.words)
|
text = text:gsub("%{(.-)%}", dataBlock.words, 1)
|
||||||
|
|
||||||
-- Recalculate positions as braces are removed
|
-- Recalculate positions as braces are removed
|
||||||
highlightData[(i-1)*3+1] = dataBlock._start - ((i-1) * 2)
|
highlightData[(i-1)*3+1] = dataBlock._start - ((i-1) * 2)
|
||||||
@@ -779,7 +832,11 @@ function onTalk(name, level, mode, message, channelId, creaturePos)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if name ~= g_game.getCharacterName() then
|
local localPlayer = g_game.getLocalPlayer()
|
||||||
|
if name ~= g_game.getCharacterName()
|
||||||
|
and isUsingIgnoreList()
|
||||||
|
and not(isUsingWhiteList()) or (isUsingWhiteList() and not(isWhitelisted(name)) and not(isAllowingVIPs() and localPlayer:hasVip(name))) then
|
||||||
|
|
||||||
if mode == MessageModes.Yell and isIgnoringYelling() then
|
if mode == MessageModes.Yell and isIgnoringYelling() then
|
||||||
return
|
return
|
||||||
elseif speaktype.private and isIgnoringPrivate() and mode ~= MessageModes.NpcFrom then
|
elseif speaktype.private and isIgnoringPrivate() and mode ~= MessageModes.NpcFrom then
|
||||||
@@ -957,107 +1014,221 @@ function onChannelList(channelList)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function loadIgnoreSettings()
|
function loadCommunicationSettings()
|
||||||
|
communicationSettings.whitelistedPlayers = {}
|
||||||
|
communicationSettings.ignoredPlayers = {}
|
||||||
|
|
||||||
local ignoreNode = g_settings.getNode('IgnorePlayers')
|
local ignoreNode = g_settings.getNode('IgnorePlayers')
|
||||||
if ignoreNode then
|
if ignoreNode then
|
||||||
for i = 1, #ignoreNode do
|
for i = 1, #ignoreNode do
|
||||||
table.insert(ignoreSettings.players, ignoreNode[i])
|
table.insert(communicationSettings.ignoredPlayers, ignoreNode[i])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
ignoreSettings.privateMessages = g_settings.getBoolean('IgnorePrivateMessages')
|
|
||||||
ignoreSettings.yelling = g_settings.getBoolean('IgnoreYelling')
|
|
||||||
end
|
|
||||||
|
|
||||||
function saveIgnoreSettings()
|
local whitelistNode = g_settings.getNode('WhitelistedPlayers')
|
||||||
local tmpSettings = {}
|
if whitelistNode then
|
||||||
for i = 1, #ignoreSettings.players do
|
for i = 1, #whitelistNode do
|
||||||
table.insert(tmpSettings, ignoreSettings.players[i])
|
table.insert(communicationSettings.whitelistedPlayers, whitelistNode[i])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
g_settings.set('IgnorePrivateMessages', ignoreSettings.privateMessages)
|
|
||||||
g_settings.set('IgnoreYelling', ignoreSettings.yelling)
|
communicationSettings.useIgnoreList = g_settings.getBoolean('UseIgnoreList')
|
||||||
g_settings.setNode('IgnorePlayers', tmpSettings)
|
communicationSettings.useWhiteList = g_settings.getBoolean('UseWhiteList')
|
||||||
|
communicationSettings.privateMessages = g_settings.getBoolean('IgnorePrivateMessages')
|
||||||
|
communicationSettings.yelling = g_settings.getBoolean('IgnoreYelling')
|
||||||
|
communicationSettings.allowVIPs = g_settings.getBoolean('AllowVIPs')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function saveCommunicationSettings()
|
||||||
|
local tmpIgnoreList = {}
|
||||||
|
local ignoredPlayers = getIgnoredPlayers()
|
||||||
|
for i = 1, #ignoredPlayers do
|
||||||
|
table.insert(tmpIgnoreList, ignoredPlayers[i])
|
||||||
|
end
|
||||||
|
|
||||||
|
local tmpWhiteList = {}
|
||||||
|
local whitelistedPlayers = getWhitelistedPlayers()
|
||||||
|
for i = 1, #whitelistedPlayers do
|
||||||
|
table.insert(tmpWhiteList, whitelistedPlayers[i])
|
||||||
|
end
|
||||||
|
|
||||||
|
g_settings.set('UseIgnoreList', communicationSettings.useIgnoreList)
|
||||||
|
g_settings.set('UseWhiteList', communicationSettings.useWhiteList)
|
||||||
|
g_settings.set('IgnorePrivateMessages', communicationSettings.privateMessages)
|
||||||
|
g_settings.set('IgnoreYelling', communicationSettings.yelling)
|
||||||
|
g_settings.setNode('IgnorePlayers', tmpIgnoreList)
|
||||||
|
g_settings.setNode('WhitelistedPlayers', tmpWhiteList)
|
||||||
|
end
|
||||||
|
|
||||||
|
function getIgnoredPlayers()
|
||||||
|
return communicationSettings.ignoredPlayers
|
||||||
|
end
|
||||||
|
|
||||||
|
function getWhitelistedPlayers()
|
||||||
|
return communicationSettings.whitelistedPlayers
|
||||||
|
end
|
||||||
|
|
||||||
|
function isUsingIgnoreList()
|
||||||
|
return communicationSettings.useIgnoreList
|
||||||
|
end
|
||||||
|
|
||||||
|
function isUsingWhiteList()
|
||||||
|
return communicationSettings.useWhiteList
|
||||||
|
end
|
||||||
function isIgnored(name)
|
function isIgnored(name)
|
||||||
return table.find(ignoreSettings.players, name, true)
|
return table.find(communicationSettings.ignoredPlayers, name, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
function addIgnoredPlayer(name)
|
function addIgnoredPlayer(name)
|
||||||
if not isIgnored(name) then
|
if isIgnored(name) then return end
|
||||||
table.insert(ignoreSettings.players, name)
|
table.insert(communicationSettings.ignoredPlayers, name)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function removeIgnoredPlayer(name)
|
function removeIgnoredPlayer(name)
|
||||||
table.removevalue(ignoreSettings.players, name)
|
table.removevalue(communicationSettings.ignoredPlayers, name)
|
||||||
|
end
|
||||||
|
|
||||||
|
function isWhitelisted(name)
|
||||||
|
return table.find(communicationSettings.whitelistedPlayers, name, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
function addWhitelistedPlayer(name)
|
||||||
|
if isWhitelisted(name) then return end
|
||||||
|
table.insert(communicationSettings.whitelistedPlayers, name)
|
||||||
|
end
|
||||||
|
|
||||||
|
function removeWhitelistedPlayer(name)
|
||||||
|
table.removevalue(communicationSettings.whitelistedPlayers, name)
|
||||||
end
|
end
|
||||||
|
|
||||||
function isIgnoringPrivate()
|
function isIgnoringPrivate()
|
||||||
return ignoreSettings.privateMessages
|
return communicationSettings.privateMessages
|
||||||
end
|
end
|
||||||
|
|
||||||
function isIgnoringYelling()
|
function isIgnoringYelling()
|
||||||
return ignoreSettings.yelling
|
return communicationSettings.yelling
|
||||||
|
end
|
||||||
|
|
||||||
|
function isAllowingVIPs()
|
||||||
|
return communicationSettings.allowVIPs
|
||||||
end
|
end
|
||||||
|
|
||||||
function onClickIgnoreButton()
|
function onClickIgnoreButton()
|
||||||
if ignoreWindow then return end
|
if communicationWindow then return end
|
||||||
ignoreWindow = g_ui.displayUI('ignorewindow')
|
communicationWindow = g_ui.displayUI('communicationwindow')
|
||||||
local ignoreListPanel = ignoreWindow:getChildById('ignoreList')
|
local ignoreListPanel = communicationWindow:getChildById('ignoreList')
|
||||||
ignoreWindow.onDestroy = function() ignoreWindow = nil end
|
local whiteListPanel = communicationWindow:getChildById('whiteList')
|
||||||
|
communicationWindow.onDestroy = function() communicationWindow = nil end
|
||||||
|
|
||||||
local removeButton = ignoreWindow:getChildById('buttonRemove')
|
local useIgnoreListBox = communicationWindow:getChildById('checkboxUseIgnoreList')
|
||||||
removeButton:disable()
|
useIgnoreListBox:setChecked(communicationSettings.useIgnoreList)
|
||||||
ignoreListPanel.onChildFocusChange = function() removeButton:enable() end
|
local useWhiteListBox = communicationWindow:getChildById('checkboxUseWhiteList')
|
||||||
removeButton.onClick = function()
|
useWhiteListBox:setChecked(communicationSettings.useWhiteList)
|
||||||
|
|
||||||
|
local removeIgnoreButton = communicationWindow:getChildById('buttonIgnoreRemove')
|
||||||
|
removeIgnoreButton:disable()
|
||||||
|
ignoreListPanel.onChildFocusChange = function() removeIgnoreButton:enable() end
|
||||||
|
removeIgnoreButton.onClick = function()
|
||||||
local selection = ignoreListPanel:getFocusedChild()
|
local selection = ignoreListPanel:getFocusedChild()
|
||||||
if selection then
|
if selection then
|
||||||
ignoreListPanel:removeChild(selection)
|
ignoreListPanel:removeChild(selection)
|
||||||
selection:destroy()
|
selection:destroy()
|
||||||
end
|
end
|
||||||
if ignoreListPanel:getChildCount() == 0 then
|
removeIgnoreButton:disable()
|
||||||
removeButton:disable()
|
end
|
||||||
|
|
||||||
|
local removeWhitelistButton = communicationWindow:getChildById('buttonWhitelistRemove')
|
||||||
|
removeWhitelistButton:disable()
|
||||||
|
whiteListPanel.onChildFocusChange = function() removeWhitelistButton:enable() end
|
||||||
|
removeWhitelistButton.onClick = function()
|
||||||
|
local selection = whiteListPanel:getFocusedChild()
|
||||||
|
if selection then
|
||||||
|
whiteListPanel:removeChild(selection)
|
||||||
|
selection:destroy()
|
||||||
end
|
end
|
||||||
|
removeWhitelistButton:disable()
|
||||||
end
|
end
|
||||||
|
|
||||||
local newlyIgnoredPlayers = {}
|
local newlyIgnoredPlayers = {}
|
||||||
local addName = ignoreWindow:getChildById('ignoreNameEdit')
|
local addIgnoreName = communicationWindow:getChildById('ignoreNameEdit')
|
||||||
local addButton = ignoreWindow:getChildById('buttonAdd')
|
local addIgnoreButton = communicationWindow:getChildById('buttonIgnoreAdd')
|
||||||
local addFunction = function()
|
local addIgnoreFunction = function()
|
||||||
if addName:getText() == '' then return end
|
local newEntry = addIgnoreName:getText()
|
||||||
if table.find(ignoreSettings.players, addName:getText()) then return end
|
if newEntry == '' then return end
|
||||||
if table.find(newlyIgnoredPlayers, addName:getText()) then return end
|
if table.find(getIgnoredPlayers(), newEntry) then return end
|
||||||
local label = g_ui.createWidget('IgnoreListLabel', ignoreListPanel)
|
if table.find(newlyIgnoredPlayers, newEntry) then return end
|
||||||
label:setText(addName:getText())
|
|
||||||
table.insert(newlyIgnoredPlayers, addName:getText())
|
|
||||||
label:setPhantom(false)
|
|
||||||
addName:setText('')
|
|
||||||
end
|
|
||||||
addButton.onClick = addFunction
|
|
||||||
ignoreWindow.onEnter = addFunction
|
|
||||||
|
|
||||||
local ignorePrivateMessageBox = ignoreWindow:getChildById('checkboxIgnorePrivateMessages')
|
|
||||||
ignorePrivateMessageBox:setChecked(ignoreSettings.privateMessages)
|
|
||||||
local ignoreYellingBox = ignoreWindow:getChildById('checkboxIgnoreYelling')
|
|
||||||
ignoreYellingBox:setChecked(ignoreSettings.yelling)
|
|
||||||
|
|
||||||
local saveButton = ignoreWindow:getChildById('buttonSave')
|
|
||||||
saveButton.onClick = function()
|
|
||||||
ignoreSettings.players = {}
|
|
||||||
for i = 1, ignoreListPanel:getChildCount() do
|
|
||||||
addIgnoredPlayer(ignoreListPanel:getChildByIndex(i):getText())
|
|
||||||
--table.insert(ignoreSettings.players, ignoreListPanel:getChildByIndex(i):getText())
|
|
||||||
end
|
|
||||||
|
|
||||||
ignoreSettings.yelling = ignoreYellingBox:isChecked()
|
|
||||||
ignoreSettings.privateMessages = ignorePrivateMessageBox:isChecked()
|
|
||||||
ignoreWindow:destroy()
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, name in pairs(ignoreSettings.players) do
|
|
||||||
local label = g_ui.createWidget('IgnoreListLabel', ignoreListPanel)
|
local label = g_ui.createWidget('IgnoreListLabel', ignoreListPanel)
|
||||||
label:setText(name)
|
label:setText(newEntry)
|
||||||
label:setPhantom(false)
|
table.insert(newlyIgnoredPlayers, newEntry)
|
||||||
|
addIgnoreName:setText('')
|
||||||
|
end
|
||||||
|
addIgnoreButton.onClick = addIgnoreFunction
|
||||||
|
|
||||||
|
local newlyWhitelistedPlayers = {}
|
||||||
|
local addWhitelistName = communicationWindow:getChildById('whitelistNameEdit')
|
||||||
|
local addWhitelistButton = communicationWindow:getChildById('buttonWhitelistAdd')
|
||||||
|
local addWhitelistFunction = function()
|
||||||
|
local newEntry = addWhitelistName:getText()
|
||||||
|
if newEntry == '' then return end
|
||||||
|
if table.find(getWhitelistedPlayers(), newEntry) then return end
|
||||||
|
if table.find(newlyWhitelistedPlayers, newEntry) then return end
|
||||||
|
local label = g_ui.createWidget('WhiteListLabel', whiteListPanel)
|
||||||
|
label:setText(newEntry)
|
||||||
|
table.insert(newlyWhitelistedPlayers, newEntry)
|
||||||
|
addWhitelistName:setText('')
|
||||||
|
end
|
||||||
|
addWhitelistButton.onClick = addWhitelistFunction
|
||||||
|
|
||||||
|
communicationWindow.onEnter = function()
|
||||||
|
if addWhitelistName:isFocused() then
|
||||||
|
addWhitelistFunction()
|
||||||
|
elseif addIgnoreName:isFocused() then
|
||||||
|
addIgnoreFunction()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local ignorePrivateMessageBox = communicationWindow:getChildById('checkboxIgnorePrivateMessages')
|
||||||
|
ignorePrivateMessageBox:setChecked(communicationSettings.privateMessages)
|
||||||
|
local ignoreYellingBox = communicationWindow:getChildById('checkboxIgnoreYelling')
|
||||||
|
ignoreYellingBox:setChecked(communicationSettings.yelling)
|
||||||
|
local allowVIPsBox = communicationWindow:getChildById('checkboxAllowVIPs')
|
||||||
|
allowVIPsBox:setChecked(communicationSettings.allowVIPs)
|
||||||
|
|
||||||
|
local saveButton = communicationWindow:recursiveGetChildById('buttonSave')
|
||||||
|
saveButton.onClick = function()
|
||||||
|
communicationSettings.ignoredPlayers = {}
|
||||||
|
for i = 1, ignoreListPanel:getChildCount() do
|
||||||
|
addIgnoredPlayer(ignoreListPanel:getChildByIndex(i):getText())
|
||||||
|
end
|
||||||
|
|
||||||
|
communicationSettings.whitelistedPlayers = {}
|
||||||
|
for i = 1, whiteListPanel:getChildCount() do
|
||||||
|
addWhitelistedPlayer(whiteListPanel:getChildByIndex(i):getText())
|
||||||
|
end
|
||||||
|
|
||||||
|
communicationSettings.useIgnoreList = useIgnoreListBox:isChecked()
|
||||||
|
communicationSettings.useWhiteList = useWhiteListBox:isChecked()
|
||||||
|
communicationSettings.yelling = ignoreYellingBox:isChecked()
|
||||||
|
communicationSettings.privateMessages = ignorePrivateMessageBox:isChecked()
|
||||||
|
communicationSettings.allowVIPs = allowVIPsBox:isChecked()
|
||||||
|
communicationWindow:destroy()
|
||||||
|
end
|
||||||
|
|
||||||
|
local cancelButton = communicationWindow:recursiveGetChildById('buttonCancel')
|
||||||
|
cancelButton.onClick = function()
|
||||||
|
communicationWindow:destroy()
|
||||||
|
end
|
||||||
|
|
||||||
|
local ignoredPlayers = getIgnoredPlayers()
|
||||||
|
for i = 1, #ignoredPlayers do
|
||||||
|
local label = g_ui.createWidget('IgnoreListLabel', ignoreListPanel)
|
||||||
|
label:setText(ignoredPlayers[i])
|
||||||
|
end
|
||||||
|
|
||||||
|
local whitelistedPlayers = getWhitelistedPlayers()
|
||||||
|
for i = 1, #whitelistedPlayers do
|
||||||
|
local label = g_ui.createWidget('WhiteListLabel', whiteListPanel)
|
||||||
|
label:setText(whitelistedPlayers[i])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1089,4 +1260,4 @@ function offline()
|
|||||||
g_keyboard.unbindKeyDown('Ctrl+R')
|
g_keyboard.unbindKeyDown('Ctrl+R')
|
||||||
end
|
end
|
||||||
clear()
|
clear()
|
||||||
end
|
end
|
@@ -56,12 +56,21 @@ Panel
|
|||||||
id: consolePanel
|
id: consolePanel
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
|
CheckBox
|
||||||
|
id: toggleChat
|
||||||
|
!tooltip: tr('Disable chat mode, allow to walk using ASDW')
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
margin-left: 13
|
||||||
|
margin-top: 8
|
||||||
|
@onCheckChange: toggleChat()
|
||||||
|
|
||||||
TabButton
|
TabButton
|
||||||
id: prevChannelButton
|
id: prevChannelButton
|
||||||
icon: /images/game/console/leftarrow
|
icon: /images/game/console/leftarrow
|
||||||
anchors.left: parent.left
|
anchors.left: toggleChat.right
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
margin-left: 6
|
margin-left: 3
|
||||||
margin-top: 6
|
margin-top: 6
|
||||||
|
|
||||||
ConsoleTabBar
|
ConsoleTabBar
|
||||||
|
@@ -1,98 +0,0 @@
|
|||||||
IgnoreListLabel < Label
|
|
||||||
font: verdana-11px-monochrome
|
|
||||||
background-color: alpha
|
|
||||||
text-offset: 2 0
|
|
||||||
focusable: true
|
|
||||||
|
|
||||||
$focus:
|
|
||||||
background-color: #ffffff22
|
|
||||||
color: #ffffff
|
|
||||||
|
|
||||||
MainWindow
|
|
||||||
id: ignoreWindow
|
|
||||||
!text: tr('Ignore List')
|
|
||||||
size: 500 240
|
|
||||||
@onEscape: self:destroy()
|
|
||||||
|
|
||||||
Label
|
|
||||||
!text: tr('Ignored players:')
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.top: parent.top
|
|
||||||
|
|
||||||
TextList
|
|
||||||
id: ignoreList
|
|
||||||
vertical-scrollbar: ignoreListScrollBar
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.top: prev.bottom
|
|
||||||
height: 150
|
|
||||||
width: 230
|
|
||||||
margin-bottom: 10
|
|
||||||
margin-top: 3
|
|
||||||
padding: 1
|
|
||||||
focusable: false
|
|
||||||
|
|
||||||
Button
|
|
||||||
id: buttonRemove
|
|
||||||
!text: tr('Remove')
|
|
||||||
width: 64
|
|
||||||
anchors.right: prev.right
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
|
|
||||||
TextEdit
|
|
||||||
id: ignoreNameEdit
|
|
||||||
anchors.left: ignoreList.right
|
|
||||||
anchors.top: ignoreList.top
|
|
||||||
width: 180
|
|
||||||
margin-left: 8
|
|
||||||
margin-right: 3
|
|
||||||
|
|
||||||
Button
|
|
||||||
id: buttonAdd
|
|
||||||
!text: tr('Add')
|
|
||||||
width: 48
|
|
||||||
height: 20
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: prev.top
|
|
||||||
|
|
||||||
CheckBox
|
|
||||||
id: checkboxIgnorePrivateMessages
|
|
||||||
!text: tr('Ignore Private Messages')
|
|
||||||
anchors.left: ignoreList.right
|
|
||||||
anchors.top: ignoreList.top
|
|
||||||
width: 180
|
|
||||||
margin-top: 25
|
|
||||||
margin-left: 8
|
|
||||||
|
|
||||||
CheckBox
|
|
||||||
id: checkboxIgnoreYelling
|
|
||||||
!text: tr('Ignore Yelling')
|
|
||||||
anchors.left: ignoreList.right
|
|
||||||
anchors.top: prev.top
|
|
||||||
width: 180
|
|
||||||
margin-top: 25
|
|
||||||
margin-left: 8
|
|
||||||
|
|
||||||
Button
|
|
||||||
id: buttonSave
|
|
||||||
!text: tr('Save')
|
|
||||||
width: 64
|
|
||||||
anchors.right: next.left
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
margin-right: 10
|
|
||||||
@onClick: self:getParent():onEnter()
|
|
||||||
|
|
||||||
Button
|
|
||||||
id: buttonCancel
|
|
||||||
!text: tr('Cancel')
|
|
||||||
width: 64
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
@onClick: self:getParent():destroy()
|
|
||||||
|
|
||||||
VerticalScrollBar
|
|
||||||
id: ignoreListScrollBar
|
|
||||||
anchors.top: ignoreList.top
|
|
||||||
anchors.bottom: ignoreList.bottom
|
|
||||||
anchors.right: ignoreList.right
|
|
||||||
step: 14
|
|
||||||
pixels-scroll: true
|
|
@@ -42,7 +42,8 @@ function init()
|
|||||||
gameBottomPanel = gameRootPanel:getChildById('gameBottomPanel')
|
gameBottomPanel = gameRootPanel:getChildById('gameBottomPanel')
|
||||||
connect(gameLeftPanel, { onVisibilityChange = onLeftPanelVisibilityChange })
|
connect(gameLeftPanel, { onVisibilityChange = onLeftPanelVisibilityChange })
|
||||||
|
|
||||||
logoutButton = modules.client_topmenu.addLeftButton('logoutButton', tr('Exit'), '/images/topbuttons/logout', tryLogout, true)
|
logoutButton = modules.client_topmenu.addLeftButton('logoutButton', tr('Exit'),
|
||||||
|
'/images/topbuttons/logout', tryLogout, true)
|
||||||
|
|
||||||
setupViewMode(0)
|
setupViewMode(0)
|
||||||
|
|
||||||
@@ -56,42 +57,19 @@ end
|
|||||||
|
|
||||||
function bindKeys()
|
function bindKeys()
|
||||||
gameRootPanel:setAutoRepeatDelay(250)
|
gameRootPanel:setAutoRepeatDelay(250)
|
||||||
g_keyboard.bindKeyDown('Up', function() changeWalkDir(North) end, gameRootPanel, true)
|
|
||||||
g_keyboard.bindKeyDown('Right', function() changeWalkDir(East) end, gameRootPanel, true)
|
bindWalkKey('Up', North)
|
||||||
g_keyboard.bindKeyDown('Down', function() changeWalkDir(South) end, gameRootPanel, true)
|
bindWalkKey('Right', East)
|
||||||
g_keyboard.bindKeyDown('Left', function() changeWalkDir(West) end, gameRootPanel, true)
|
bindWalkKey('Down', South)
|
||||||
g_keyboard.bindKeyDown('Numpad8', function() changeWalkDir(North) end, gameRootPanel, true)
|
bindWalkKey('Left', West)
|
||||||
g_keyboard.bindKeyDown('Numpad9', function() changeWalkDir(NorthEast) end, gameRootPanel, true)
|
bindWalkKey('Numpad8', North)
|
||||||
g_keyboard.bindKeyDown('Numpad6', function() changeWalkDir(East) end, gameRootPanel, true)
|
bindWalkKey('Numpad9', NorthEast)
|
||||||
g_keyboard.bindKeyDown('Numpad3', function() changeWalkDir(SouthEast) end, gameRootPanel, true)
|
bindWalkKey('Numpad6', East)
|
||||||
g_keyboard.bindKeyDown('Numpad2', function() changeWalkDir(South) end, gameRootPanel, true)
|
bindWalkKey('Numpad3', SouthEast)
|
||||||
g_keyboard.bindKeyDown('Numpad1', function() changeWalkDir(SouthWest) end, gameRootPanel, true)
|
bindWalkKey('Numpad2', South)
|
||||||
g_keyboard.bindKeyDown('Numpad4', function() changeWalkDir(West) end, gameRootPanel, true)
|
bindWalkKey('Numpad1', SouthWest)
|
||||||
g_keyboard.bindKeyDown('Numpad7', function() changeWalkDir(NorthWest) end, gameRootPanel, true)
|
bindWalkKey('Numpad4', West)
|
||||||
g_keyboard.bindKeyUp('Up', function() changeWalkDir(North, true) end, gameRootPanel, true)
|
bindWalkKey('Numpad7', NorthWest)
|
||||||
g_keyboard.bindKeyUp('Right', function() changeWalkDir(East, true) end, gameRootPanel, true)
|
|
||||||
g_keyboard.bindKeyUp('Down', function() changeWalkDir(South, true) end, gameRootPanel, true)
|
|
||||||
g_keyboard.bindKeyUp('Left', function() changeWalkDir(West, true) end, gameRootPanel, true)
|
|
||||||
g_keyboard.bindKeyUp('Numpad8', function() changeWalkDir(North, true) end, gameRootPanel, true)
|
|
||||||
g_keyboard.bindKeyUp('Numpad9', function() changeWalkDir(NorthEast, true) end, gameRootPanel, true)
|
|
||||||
g_keyboard.bindKeyUp('Numpad6', function() changeWalkDir(East, true) end, gameRootPanel, true)
|
|
||||||
g_keyboard.bindKeyUp('Numpad3', function() changeWalkDir(SouthEast, true) end, gameRootPanel, true)
|
|
||||||
g_keyboard.bindKeyUp('Numpad2', function() changeWalkDir(South, true) end, gameRootPanel, true)
|
|
||||||
g_keyboard.bindKeyUp('Numpad1', function() changeWalkDir(SouthWest, true) end, gameRootPanel, true)
|
|
||||||
g_keyboard.bindKeyUp('Numpad4', function() changeWalkDir(West, true) end, gameRootPanel, true)
|
|
||||||
g_keyboard.bindKeyUp('Numpad7', function() changeWalkDir(NorthWest, true) end, gameRootPanel, true)
|
|
||||||
g_keyboard.bindKeyPress('Up', function() smartWalk(North) end, gameRootPanel)
|
|
||||||
g_keyboard.bindKeyPress('Right', function() smartWalk(East) end, gameRootPanel)
|
|
||||||
g_keyboard.bindKeyPress('Down', function() smartWalk(South) end, gameRootPanel)
|
|
||||||
g_keyboard.bindKeyPress('Left', function() smartWalk(West) end, gameRootPanel)
|
|
||||||
g_keyboard.bindKeyPress('Numpad8', function() smartWalk(North) end, gameRootPanel)
|
|
||||||
g_keyboard.bindKeyPress('Numpad9', function() smartWalk(NorthEast) end, gameRootPanel)
|
|
||||||
g_keyboard.bindKeyPress('Numpad6', function() smartWalk(East) end, gameRootPanel)
|
|
||||||
g_keyboard.bindKeyPress('Numpad3', function() smartWalk(SouthEast) end, gameRootPanel)
|
|
||||||
g_keyboard.bindKeyPress('Numpad2', function() smartWalk(South) end, gameRootPanel)
|
|
||||||
g_keyboard.bindKeyPress('Numpad1', function() smartWalk(SouthWest) end, gameRootPanel)
|
|
||||||
g_keyboard.bindKeyPress('Numpad4', function() smartWalk(West) end, gameRootPanel)
|
|
||||||
g_keyboard.bindKeyPress('Numpad7', function() smartWalk(NorthWest) end, gameRootPanel)
|
|
||||||
|
|
||||||
g_keyboard.bindKeyPress('Ctrl+Up', function() g_game.turn(North) changeWalkDir(North) end, gameRootPanel)
|
g_keyboard.bindKeyPress('Ctrl+Up', function() g_game.turn(North) changeWalkDir(North) end, gameRootPanel)
|
||||||
g_keyboard.bindKeyPress('Ctrl+Right', function() g_game.turn(East) changeWalkDir(East) end, gameRootPanel)
|
g_keyboard.bindKeyPress('Ctrl+Right', function() g_game.turn(East) changeWalkDir(East) end, gameRootPanel)
|
||||||
@@ -104,12 +82,24 @@ function bindKeys()
|
|||||||
g_keyboard.bindKeyPress('Escape', function() g_game.cancelAttackAndFollow() end, gameRootPanel)
|
g_keyboard.bindKeyPress('Escape', function() g_game.cancelAttackAndFollow() end, gameRootPanel)
|
||||||
g_keyboard.bindKeyPress('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel)
|
g_keyboard.bindKeyPress('Ctrl+=', function() gameMapPanel:zoomIn() end, gameRootPanel)
|
||||||
g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel)
|
g_keyboard.bindKeyPress('Ctrl+-', function() gameMapPanel:zoomOut() end, gameRootPanel)
|
||||||
g_keyboard.bindKeyDown('Ctrl+Q', logout, gameRootPanel)
|
g_keyboard.bindKeyDown('Ctrl+Q', function() tryLogout(false) end, gameRootPanel)
|
||||||
g_keyboard.bindKeyDown('Ctrl+L', logout, gameRootPanel)
|
g_keyboard.bindKeyDown('Ctrl+L', function() tryLogout(false) end, gameRootPanel)
|
||||||
g_keyboard.bindKeyDown('Ctrl+W', function() g_map.cleanTexts() modules.game_textmessage.clearMessages() end, gameRootPanel)
|
g_keyboard.bindKeyDown('Ctrl+W', function() g_map.cleanTexts() modules.game_textmessage.clearMessages() end, gameRootPanel)
|
||||||
g_keyboard.bindKeyDown('Ctrl+.', nextViewMode, gameRootPanel)
|
g_keyboard.bindKeyDown('Ctrl+.', nextViewMode, gameRootPanel)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function bindWalkKey(key, dir)
|
||||||
|
g_keyboard.bindKeyDown(key, function() changeWalkDir(dir) end)
|
||||||
|
g_keyboard.bindKeyUp(key, function() changeWalkDir(dir, true) end)
|
||||||
|
g_keyboard.bindKeyPress(key, function() smartWalk(dir) end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function unbindWalkKey(key)
|
||||||
|
g_keyboard.unbindKeyDown(key)
|
||||||
|
g_keyboard.unbindKeyUp(key)
|
||||||
|
g_keyboard.unbindKeyPress(key)
|
||||||
|
end
|
||||||
|
|
||||||
function terminate()
|
function terminate()
|
||||||
save()
|
save()
|
||||||
hide()
|
hide()
|
||||||
@@ -215,8 +205,8 @@ function tryExit()
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local exitFunc = function() logout() forceExit() end
|
local exitFunc = function() g_game.safeLogout() forceExit() end
|
||||||
local logoutFunc = function() logout() exitWindow:destroy() exitWindow = nil end
|
local logoutFunc = function() g_game.safeLogout() exitWindow:destroy() exitWindow = nil end
|
||||||
local cancelFunc = function() exitWindow:destroy() exitWindow = nil end
|
local cancelFunc = function() exitWindow:destroy() exitWindow = nil end
|
||||||
|
|
||||||
exitWindow = displayGeneralBox(tr('Exit'), tr("If you shut down the program, your character might stay in the game.\nClick on 'Logout' to ensure that you character leaves the game properly.\nClick on 'Exit' if you want to exit the program without logging out your character."),
|
exitWindow = displayGeneralBox(tr('Exit'), tr("If you shut down the program, your character might stay in the game.\nClick on 'Logout' to ensure that you character leaves the game properly.\nClick on 'Exit' if you want to exit the program without logging out your character."),
|
||||||
@@ -228,29 +218,55 @@ function tryExit()
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function logout()
|
function tryLogout(prompt)
|
||||||
if g_game.isOnline() then
|
if type(prompt) ~= "boolean" then
|
||||||
g_game.safeLogout()
|
prompt = true
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
function tryLogout()
|
|
||||||
if not g_game.isOnline() then
|
if not g_game.isOnline() then
|
||||||
exit()
|
exit()
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if logoutWindow then
|
if logoutWindow then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local yesCallback = function() logout() logoutWindow:destroy() logoutWindow=nil end
|
local msg, yesCallback
|
||||||
local noCallback = function() logoutWindow:destroy() logoutWindow=nil end
|
if not g_game.isConnectionOk() then
|
||||||
|
msg = 'Your connection is failing, if you logout now your character will be still online, do you want to force logout?'
|
||||||
|
|
||||||
logoutWindow = displayGeneralBox(tr('Logout'), tr('Are you sure you want to logout?'), {
|
yesCallback = function()
|
||||||
{ text=tr('Yes'), callback=yesCallback },
|
g_game.forceLogout()
|
||||||
{ text=tr('No'), callback=noCallback },
|
if logoutWindow then
|
||||||
anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
|
logoutWindow:destroy()
|
||||||
|
logoutWindow=nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
msg = 'Are you sure you want to logout?'
|
||||||
|
|
||||||
|
yesCallback = function()
|
||||||
|
g_game.safeLogout()
|
||||||
|
if logoutWindow then
|
||||||
|
logoutWindow:destroy()
|
||||||
|
logoutWindow=nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local noCallback = function()
|
||||||
|
logoutWindow:destroy()
|
||||||
|
logoutWindow=nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if prompt then
|
||||||
|
logoutWindow = displayGeneralBox(tr('Logout'), tr(msg), {
|
||||||
|
{ text=tr('Yes'), callback=yesCallback },
|
||||||
|
{ text=tr('No'), callback=noCallback },
|
||||||
|
anchor=AnchorHorizontalCenter}, yesCallback, noCallback)
|
||||||
|
else
|
||||||
|
yesCallback()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function stopSmartWalk()
|
function stopSmartWalk()
|
||||||
@@ -462,17 +478,20 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
|||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
|
local localPosition = localPlayer:getPosition()
|
||||||
if not classic then shortcut = '(Alt)' else shortcut = nil end
|
if not classic then shortcut = '(Alt)' else shortcut = nil end
|
||||||
if g_game.getAttackingCreature() ~= creatureThing then
|
if creatureThing:getPosition().z == localPosition.z then
|
||||||
menu:addOption(tr('Attack'), function() g_game.attack(creatureThing) end, shortcut)
|
if g_game.getAttackingCreature() ~= creatureThing then
|
||||||
else
|
menu:addOption(tr('Attack'), function() g_game.attack(creatureThing) end, shortcut)
|
||||||
menu:addOption(tr('Stop Attack'), function() g_game.cancelAttack() end, shortcut)
|
else
|
||||||
end
|
menu:addOption(tr('Stop Attack'), function() g_game.cancelAttack() end, shortcut)
|
||||||
|
end
|
||||||
if g_game.getFollowingCreature() ~= creatureThing then
|
|
||||||
menu:addOption(tr('Follow'), function() g_game.follow(creatureThing) end)
|
if g_game.getFollowingCreature() ~= creatureThing then
|
||||||
else
|
menu:addOption(tr('Follow'), function() g_game.follow(creatureThing) end)
|
||||||
menu:addOption(tr('Stop Follow'), function() g_game.cancelFollow() end)
|
else
|
||||||
|
menu:addOption(tr('Stop Follow'), function() g_game.cancelFollow() end)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if creatureThing:isPlayer() then
|
if creatureThing:isPlayer() then
|
||||||
@@ -518,7 +537,7 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if modules.game_ruleviolation.hasWindowAccess() then
|
if modules.game_ruleviolation.hasWindowAccess() and creatureThing:isPlayer() then
|
||||||
menu:addSeparator()
|
menu:addSeparator()
|
||||||
menu:addOption(tr('Rule Violation'), function() modules.game_ruleviolation.show(creatureThing:getName()) end)
|
menu:addOption(tr('Rule Violation'), function() modules.game_ruleviolation.show(creatureThing:getName()) end)
|
||||||
end
|
end
|
||||||
@@ -530,7 +549,7 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
|||||||
menu:display(menuPosition)
|
menu:display(menuPosition)
|
||||||
end
|
end
|
||||||
|
|
||||||
function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing)
|
function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing, attackCreature)
|
||||||
local keyboardModifiers = g_keyboard.getModifiers()
|
local keyboardModifiers = g_keyboard.getModifiers()
|
||||||
|
|
||||||
if not modules.client_options.getOption('classicControl') then
|
if not modules.client_options.getOption('classicControl') then
|
||||||
@@ -556,7 +575,10 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
elseif creatureThing and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
elseif attackCreature and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||||
|
g_game.attack(attackCreature)
|
||||||
|
return true
|
||||||
|
elseif creatureThing and creatureThing:getPosition().z == autoWalkPos.z and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||||
g_game.attack(creatureThing)
|
g_game.attack(creatureThing)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@@ -565,7 +587,10 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
|
|||||||
else
|
else
|
||||||
if useThing and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseRightButton and not g_mouse.isPressed(MouseLeftButton) then
|
if useThing and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseRightButton and not g_mouse.isPressed(MouseLeftButton) then
|
||||||
local player = g_game.getLocalPlayer()
|
local player = g_game.getLocalPlayer()
|
||||||
if creatureThing and creatureThing ~= player then
|
if attackCreature and attackCreature ~= player then
|
||||||
|
g_game.attack(attackCreature)
|
||||||
|
return true
|
||||||
|
elseif creatureThing and creatureThing ~= player and creatureThing:getPosition().z == autoWalkPos.z then
|
||||||
g_game.attack(creatureThing)
|
g_game.attack(creatureThing)
|
||||||
return true
|
return true
|
||||||
elseif useThing:isContainer() then
|
elseif useThing:isContainer() then
|
||||||
@@ -593,7 +618,10 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
|
|||||||
elseif useThing and keyboardModifiers == KeyboardCtrlModifier and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
elseif useThing and keyboardModifiers == KeyboardCtrlModifier and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||||
createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
||||||
return true
|
return true
|
||||||
elseif creatureThing and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
elseif attackCreature and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||||
|
g_game.attack(attackCreature)
|
||||||
|
return true
|
||||||
|
elseif creatureThing and creatureThing:getPosition().z == autoWalkPos.z and g_keyboard.isAltPressed() and (mouseButton == MouseLeftButton or mouseButton == MouseRightButton) then
|
||||||
g_game.attack(creatureThing)
|
g_game.attack(creatureThing)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@@ -654,6 +682,8 @@ function moveStackableItem(item, toPos)
|
|||||||
end
|
end
|
||||||
g_keyboard.bindKeyPress("Up", function() check() spinbox:up() end, spinbox)
|
g_keyboard.bindKeyPress("Up", function() check() spinbox:up() end, spinbox)
|
||||||
g_keyboard.bindKeyPress("Down", function() check() spinbox:down() end, spinbox)
|
g_keyboard.bindKeyPress("Down", function() check() spinbox:down() end, spinbox)
|
||||||
|
g_keyboard.bindKeyPress("Right", function() check() spinbox:up() end, spinbox)
|
||||||
|
g_keyboard.bindKeyPress("Left", function() check() spinbox:down() end, spinbox)
|
||||||
g_keyboard.bindKeyPress("PageUp", function() check() spinbox:setValue(spinbox:getValue()+10) end, spinbox)
|
g_keyboard.bindKeyPress("PageUp", function() check() spinbox:setValue(spinbox:getValue()+10) end, spinbox)
|
||||||
g_keyboard.bindKeyPress("PageDown", function() check() spinbox:setValue(spinbox:getValue()-10) end, spinbox)
|
g_keyboard.bindKeyPress("PageDown", function() check() spinbox:setValue(spinbox:getValue()-10) end, spinbox)
|
||||||
|
|
||||||
|
@@ -6,11 +6,11 @@ CountWindow < MainWindow
|
|||||||
SpinBox
|
SpinBox
|
||||||
id: spinBox
|
id: spinBox
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: parent.bottom
|
anchors.top: parent.top
|
||||||
width: 0
|
width: 1
|
||||||
height: 0
|
height: 1
|
||||||
phantom: true
|
phantom: true
|
||||||
padding-bottom: -40
|
margin-top: 2
|
||||||
focusable: true
|
focusable: true
|
||||||
|
|
||||||
Item
|
Item
|
||||||
|
@@ -78,15 +78,21 @@ function UIGameMap:onMouseRelease(mousePosition, mouseButton)
|
|||||||
local useThing
|
local useThing
|
||||||
local creatureThing
|
local creatureThing
|
||||||
local multiUseThing
|
local multiUseThing
|
||||||
|
local attackCreature
|
||||||
|
|
||||||
local tile = self:getTile(mousePosition)
|
local tile = self:getTile(mousePosition)
|
||||||
if tile then
|
if tile then
|
||||||
lookThing = tile:getTopLookThing()
|
lookThing = tile:getTopLookThing()
|
||||||
useThing = tile:getTopUseThing()
|
useThing = tile:getTopUseThing()
|
||||||
creatureThing = tile:getTopCreature()
|
creatureThing = tile:getTopCreature()
|
||||||
|
end
|
||||||
|
|
||||||
|
local autoWalkTile = g_map.getTile(autoWalkPos)
|
||||||
|
if autoWalkTile then
|
||||||
|
attackCreature = autoWalkTile:getTopCreature()
|
||||||
end
|
end
|
||||||
|
|
||||||
local ret = modules.game_interface.processMouseAction(mousePosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing)
|
local ret = modules.game_interface.processMouseAction(mousePosition, mouseButton, autoWalkPos, lookThing, useThing, creatureThing, attackCreature)
|
||||||
if ret then
|
if ret then
|
||||||
self.allowNextRelease = false
|
self.allowNextRelease = false
|
||||||
end
|
end
|
||||||
|
@@ -86,7 +86,7 @@ function UIItem:onMouseRelease(mousePosition, mouseButton)
|
|||||||
g_game.look(item)
|
g_game.look(item)
|
||||||
self.cancelNextRelease = true
|
self.cancelNextRelease = true
|
||||||
return true
|
return true
|
||||||
elseif modules.game_interface.processMouseAction(mousePosition, mouseButton, nil, item, item, nil, item) then
|
elseif modules.game_interface.processMouseAction(mousePosition, mouseButton, nil, item, item, nil, nil) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
|
@@ -151,8 +151,7 @@ function onTradeTypeChange(radioTabs, selected, deselected)
|
|||||||
ignoreCapacity:setVisible(currentTradeType == BUY)
|
ignoreCapacity:setVisible(currentTradeType == BUY)
|
||||||
ignoreEquipped:setVisible(currentTradeType == SELL)
|
ignoreEquipped:setVisible(currentTradeType == SELL)
|
||||||
showAllItems:setVisible(currentTradeType == SELL)
|
showAllItems:setVisible(currentTradeType == SELL)
|
||||||
sellAllButton:setVisible(false)
|
sellAllButton:setVisible(currentTradeType == SELL)
|
||||||
--sellAllButton:setVisible(currentTradeType == SELL)
|
|
||||||
|
|
||||||
refreshTradeItems()
|
refreshTradeItems()
|
||||||
refreshPlayerGoods()
|
refreshPlayerGoods()
|
||||||
|
@@ -252,7 +252,6 @@ MainWindow
|
|||||||
margin-right: 10
|
margin-right: 10
|
||||||
visible: false
|
visible: false
|
||||||
@onClick: modules.game_npctrade.sellAll()
|
@onClick: modules.game_npctrade.sellAll()
|
||||||
visible: false
|
|
||||||
|
|
||||||
Button
|
Button
|
||||||
id: tradeButton
|
id: tradeButton
|
||||||
|
@@ -47,7 +47,7 @@ function openWindow()
|
|||||||
deathWindow = nil
|
deathWindow = nil
|
||||||
end
|
end
|
||||||
local cancelFunc = function()
|
local cancelFunc = function()
|
||||||
modules.game_interface.logout()
|
g_game.safeLogout()
|
||||||
cancelButton:getParent():destroy()
|
cancelButton:getParent():destroy()
|
||||||
deathWindow = nil
|
deathWindow = nil
|
||||||
end
|
end
|
||||||
|
@@ -18,7 +18,7 @@ function isLoaded()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function load()
|
function load()
|
||||||
local version = g_game.getProtocolVersion()
|
local version = g_game.getClientVersion()
|
||||||
|
|
||||||
local datPath, sprPath
|
local datPath, sprPath
|
||||||
if filename then
|
if filename then
|
||||||
|
@@ -88,6 +88,23 @@ function isHiddingOffline()
|
|||||||
return settings['hideOffline']
|
return settings['hideOffline']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function getSortedBy()
|
||||||
|
local settings = g_settings.getNode('VipList')
|
||||||
|
if not settings then
|
||||||
|
return 'status'
|
||||||
|
end
|
||||||
|
return settings['sortedBy']
|
||||||
|
end
|
||||||
|
|
||||||
|
function sortBy(state)
|
||||||
|
settings = {}
|
||||||
|
settings['sortedBy'] = state
|
||||||
|
g_settings.mergeNode('VipList', settings)
|
||||||
|
|
||||||
|
refresh()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function onAddVip(id, name, state)
|
function onAddVip(id, name, state)
|
||||||
local vipList = vipWindow:getChildById('contentsPanel')
|
local vipList = vipWindow:getChildById('contentsPanel')
|
||||||
|
|
||||||
@@ -118,13 +135,13 @@ function onAddVip(id, name, state)
|
|||||||
|
|
||||||
for i=1,childrenCount do
|
for i=1,childrenCount do
|
||||||
local child = vipList:getChildByIndex(i)
|
local child = vipList:getChildByIndex(i)
|
||||||
if state == VipState.Online and child.vipState ~= VipState.Online then
|
if state == VipState.Online and child.vipState ~= VipState.Online and getSortedBy() == 'status' then
|
||||||
vipList:insertChild(i, label)
|
vipList:insertChild(i, label)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if (state ~= VipState.Online and child.vipState ~= VipState.Online)
|
if ((state ~= VipState.Online and child.vipState ~= VipState.Online)
|
||||||
or (state == VipState.Online and child.vipState == VipState.Online) then
|
or (state == VipState.Online and child.vipState == VipState.Online)) or getSortedBy() == 'name' then
|
||||||
|
|
||||||
local childText = child:getText():lower()
|
local childText = child:getText():lower()
|
||||||
local length = math.min(childText:len(), nameLower:len())
|
local length = math.min(childText:len(), nameLower:len())
|
||||||
@@ -167,6 +184,14 @@ function onVipListMousePress(widget, mousePos, mouseButton)
|
|||||||
else
|
else
|
||||||
menu:addOption(tr('Show Offline'), function() hideOffline(false) end)
|
menu:addOption(tr('Show Offline'), function() hideOffline(false) end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if not(getSortedBy() == 'name') then
|
||||||
|
menu:addOption(tr('Sort by name'), function() sortBy('name') end)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not(getSortedBy() == 'status') then
|
||||||
|
menu:addOption(tr('Sort by status'), function() sortBy('status') end)
|
||||||
|
end
|
||||||
|
|
||||||
menu:display(mousePos)
|
menu:display(mousePos)
|
||||||
|
|
||||||
@@ -196,6 +221,15 @@ function onVipListLabelMousePress(widget, mousePos, mouseButton)
|
|||||||
else
|
else
|
||||||
menu:addOption(tr('Show Offline'), function() hideOffline(false) end)
|
menu:addOption(tr('Show Offline'), function() hideOffline(false) end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if not(getSortedBy() == 'name') then
|
||||||
|
menu:addOption(tr('Sort by name'), function() sortBy('name') end)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not(getSortedBy() == 'status') then
|
||||||
|
menu:addOption(tr('Sort by status'), function() sortBy('status') end)
|
||||||
|
end
|
||||||
|
|
||||||
menu:display(mousePos)
|
menu:display(mousePos)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@@ -6,7 +6,7 @@ end
|
|||||||
|
|
||||||
function g_game.chooseRsa(host)
|
function g_game.chooseRsa(host)
|
||||||
if currentRsa ~= CIPSOFT_RSA and currentRsa ~= OTSERV_RSA then return end
|
if currentRsa ~= CIPSOFT_RSA and currentRsa ~= OTSERV_RSA then return end
|
||||||
if string.ends(host, '.tibia.com') or string.ends(host, '.cipsoft.com') then
|
if host:ends('.tibia.com') or host:ends('.cipsoft.com') then
|
||||||
g_game.setRsa(CIPSOFT_RSA)
|
g_game.setRsa(CIPSOFT_RSA)
|
||||||
|
|
||||||
if g_app.getOs() == 'windows' then
|
if g_app.getOs() == 'windows' then
|
||||||
@@ -32,22 +32,29 @@ function g_game.isOfficialTibia()
|
|||||||
return currentRsa == CIPSOFT_RSA
|
return currentRsa == CIPSOFT_RSA
|
||||||
end
|
end
|
||||||
|
|
||||||
function g_game.getSupportedProtocols()
|
function g_game.getSupportedClients()
|
||||||
return {
|
return {
|
||||||
810, 811, 840, 842, 850, 853, 854,
|
810, 811, 840, 842, 850, 853, 854,
|
||||||
860, 861, 862, 870, 910, 940, 944,
|
860, 861, 862, 870, 910, 940, 944,
|
||||||
953, 954, 960, 961, 963, 970, 971,
|
953, 954, 960, 961, 963, 970, 980,
|
||||||
973, 974
|
981, 982, 983, 984, 985, 986, 1001,
|
||||||
|
1002, 1010
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function g_game.getSupportedClients(protocol)
|
function g_game.getProtocolVersionForClient(client)
|
||||||
clients = {
|
clients = {
|
||||||
[971] = {980},
|
[980] = 971,
|
||||||
[973] = {981},
|
[981] = 973,
|
||||||
[974] = {982}
|
[982] = 974,
|
||||||
|
[983] = 975,
|
||||||
|
[984] = 976,
|
||||||
|
[985] = 977,
|
||||||
|
[986] = 978,
|
||||||
|
[1001] = 979,
|
||||||
|
[1002] = 980,
|
||||||
}
|
}
|
||||||
return clients[protocol] or {protocol}
|
return clients[client] or client
|
||||||
end
|
end
|
||||||
|
|
||||||
g_game.setRsa(OTSERV_RSA)
|
g_game.setRsa(OTSERV_RSA)
|
||||||
|
@@ -353,6 +353,8 @@ namespace Otc
|
|||||||
GameForceFirstAutoWalkStep = 37,
|
GameForceFirstAutoWalkStep = 37,
|
||||||
GameMinimapRemove = 38,
|
GameMinimapRemove = 38,
|
||||||
GameDoubleShopSellAmount = 39,
|
GameDoubleShopSellAmount = 39,
|
||||||
|
GameContainerPagination = 40,
|
||||||
|
GameThingMarks = 41,
|
||||||
// 51-100 reserved to be defined in lua
|
// 51-100 reserved to be defined in lua
|
||||||
LastGameFeature = 101
|
LastGameFeature = 101
|
||||||
};
|
};
|
||||||
|
@@ -128,7 +128,7 @@ void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWal
|
|||||||
dest -= datType->getDisplacement() * scaleFactor;
|
dest -= datType->getDisplacement() * scaleFactor;
|
||||||
datType->draw(dest, scaleFactor, 0, xPattern, 0, 0, animationPhase, lightView);
|
datType->draw(dest, scaleFactor, 0, xPattern, 0, 0, animationPhase, lightView);
|
||||||
dest += getDisplacement() * scaleFactor;
|
dest += getDisplacement() * scaleFactor;
|
||||||
zPattern = 1;
|
zPattern = std::min(1, getNumPatternZ() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
PointF jumpOffset = m_jumpOffset * scaleFactor;
|
PointF jumpOffset = m_jumpOffset * scaleFactor;
|
||||||
|
@@ -99,6 +99,11 @@ void Game::resetGameStates()
|
|||||||
m_walkEvent = nullptr;
|
m_walkEvent = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(m_checkConnectionEvent) {
|
||||||
|
m_checkConnectionEvent->cancel();
|
||||||
|
m_checkConnectionEvent = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
m_containers.clear();
|
m_containers.clear();
|
||||||
m_vips.clear();
|
m_vips.clear();
|
||||||
m_gmActions.clear();
|
m_gmActions.clear();
|
||||||
@@ -183,6 +188,16 @@ void Game::processGameStart()
|
|||||||
g_game.ping();
|
g_game.ping();
|
||||||
}, m_pingDelay);
|
}, m_pingDelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_checkConnectionEvent = g_dispatcher.cycleEvent([this] {
|
||||||
|
if(!g_game.isConnectionOk() && !m_connectionFailWarned) {
|
||||||
|
g_lua.callGlobalField("g_game", "onConnectionFailing", true);
|
||||||
|
m_connectionFailWarned = true;
|
||||||
|
} else if(g_game.isConnectionOk() && m_connectionFailWarned) {
|
||||||
|
g_lua.callGlobalField("g_game", "onConnectionFailing", false);
|
||||||
|
m_connectionFailWarned = false;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::processGameEnd()
|
void Game::processGameEnd()
|
||||||
@@ -190,6 +205,11 @@ void Game::processGameEnd()
|
|||||||
m_online = false;
|
m_online = false;
|
||||||
g_lua.callGlobalField("g_game", "onGameEnd");
|
g_lua.callGlobalField("g_game", "onGameEnd");
|
||||||
|
|
||||||
|
if(m_connectionFailWarned) {
|
||||||
|
g_lua.callGlobalField("g_game", "onConnectionFailing", false);
|
||||||
|
m_connectionFailWarned = false;
|
||||||
|
}
|
||||||
|
|
||||||
// reset game state
|
// reset game state
|
||||||
resetGameStates();
|
resetGameStates();
|
||||||
|
|
||||||
@@ -554,7 +574,7 @@ bool Game::walk(Otc::Direction direction)
|
|||||||
if(m_lastWalkDir != direction) {
|
if(m_lastWalkDir != direction) {
|
||||||
// must add a new walk event
|
// must add a new walk event
|
||||||
float ticks = m_localPlayer->getStepTicksLeft();
|
float ticks = m_localPlayer->getStepTicksLeft();
|
||||||
if(ticks < 0) { ticks = 0; }
|
if(ticks <= 0) { ticks = 1; }
|
||||||
|
|
||||||
if(m_walkEvent) {
|
if(m_walkEvent) {
|
||||||
m_walkEvent->cancel();
|
m_walkEvent->cancel();
|
||||||
@@ -697,15 +717,16 @@ void Game::autoWalk(std::vector<Otc::Direction> dirs)
|
|||||||
|
|
||||||
auto it = dirs.begin();
|
auto it = dirs.begin();
|
||||||
Otc::Direction direction = *it;
|
Otc::Direction direction = *it;
|
||||||
if(m_localPlayer->canWalk(direction)) {
|
if(!m_localPlayer->canWalk(direction))
|
||||||
TilePtr toTile = g_map.getTile(m_localPlayer->getPosition().translatedToDirection(direction));
|
return;
|
||||||
if(toTile && toTile->isWalkable() && !m_localPlayer->isServerWalking()) {
|
|
||||||
m_localPlayer->preWalk(direction);
|
|
||||||
|
|
||||||
if(getFeature(Otc::GameForceFirstAutoWalkStep)) {
|
TilePtr toTile = g_map.getTile(m_localPlayer->getPosition().translatedToDirection(direction));
|
||||||
forceWalk(direction);
|
if(toTile && toTile->isWalkable() && !m_localPlayer->isServerWalking()) {
|
||||||
dirs.erase(it);
|
m_localPlayer->preWalk(direction);
|
||||||
}
|
|
||||||
|
if(getFeature(Otc::GameForceFirstAutoWalkStep)) {
|
||||||
|
forceWalk(direction);
|
||||||
|
dirs.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1129,7 +1150,7 @@ void Game::removeVip(int playerId)
|
|||||||
{
|
{
|
||||||
if(!canPerformGameAction())
|
if(!canPerformGameAction())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto it = m_vips.find(playerId);
|
auto it = m_vips.find(playerId);
|
||||||
if(it == m_vips.end())
|
if(it == m_vips.end())
|
||||||
return;
|
return;
|
||||||
@@ -1379,7 +1400,7 @@ void Game::setProtocolVersion(int version)
|
|||||||
if(isOnline())
|
if(isOnline())
|
||||||
stdext::throw_exception("Unable to change protocol version while online");
|
stdext::throw_exception("Unable to change protocol version while online");
|
||||||
|
|
||||||
if(version != 0 && (version < 810 || version > 974))
|
if(version != 0 && (version < 810 || version > 1010))
|
||||||
stdext::throw_exception(stdext::format("Protocol version %d not supported", version));
|
stdext::throw_exception(stdext::format("Protocol version %d not supported", version));
|
||||||
|
|
||||||
m_features.reset();
|
m_features.reset();
|
||||||
@@ -1443,6 +1464,14 @@ void Game::setProtocolVersion(int version)
|
|||||||
enableFeature(Otc::GameNewSpeedLaw);
|
enableFeature(Otc::GameNewSpeedLaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(version >= 976) {
|
||||||
|
enableFeature(Otc::GameContainerPagination);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(version >= 979) {
|
||||||
|
enableFeature(Otc::GameThingMarks);
|
||||||
|
}
|
||||||
|
|
||||||
m_protocolVersion = version;
|
m_protocolVersion = version;
|
||||||
|
|
||||||
Proto::buildMessageModesMap(version);
|
Proto::buildMessageModesMap(version);
|
||||||
@@ -1458,7 +1487,7 @@ void Game::setClientVersion(int version)
|
|||||||
if(isOnline())
|
if(isOnline())
|
||||||
stdext::throw_exception("Unable to change client version while online");
|
stdext::throw_exception("Unable to change client version while online");
|
||||||
|
|
||||||
if(version != 0 && (version < 810 || version > 982))
|
if(version != 0 && (version < 810 || version > 1010))
|
||||||
stdext::throw_exception(stdext::format("Client version %d not supported", version));
|
stdext::throw_exception(stdext::format("Client version %d not supported", version));
|
||||||
|
|
||||||
m_clientVersion = version;
|
m_clientVersion = version;
|
||||||
|
@@ -231,7 +231,7 @@ public:
|
|||||||
void openRuleViolation(const std::string& reporter);
|
void openRuleViolation(const std::string& reporter);
|
||||||
void closeRuleViolation(const std::string& reporter);
|
void closeRuleViolation(const std::string& reporter);
|
||||||
void cancelRuleViolation();
|
void cancelRuleViolation();
|
||||||
|
|
||||||
// reports
|
// reports
|
||||||
void reportBug(const std::string& comment);
|
void reportBug(const std::string& comment);
|
||||||
void reportRuleViolation(const std::string& target, int reason, int action, const std::string& comment, const std::string& statement, int statementId, bool ipBanishment);
|
void reportRuleViolation(const std::string& target, int reason, int action, const std::string& comment, const std::string& statement, int statementId, bool ipBanishment);
|
||||||
@@ -281,6 +281,7 @@ public:
|
|||||||
bool isDead() { return m_dead; }
|
bool isDead() { return m_dead; }
|
||||||
bool isAttacking() { return !!m_attackingCreature; }
|
bool isAttacking() { return !!m_attackingCreature; }
|
||||||
bool isFollowing() { return !!m_followingCreature; }
|
bool isFollowing() { return !!m_followingCreature; }
|
||||||
|
bool isConnectionOk() { return m_protocolGame && m_protocolGame->getElapsedTicksSinceLastRead() < 5000; }
|
||||||
|
|
||||||
int getPing() { return m_ping >= 0 ? std::max(m_ping, m_pingTimer.elapsed_millis()) : -1; }
|
int getPing() { return m_ping >= 0 ? std::max(m_ping, m_pingTimer.elapsed_millis()) : -1; }
|
||||||
ContainerPtr getContainer(int index) { return m_containers[index]; }
|
ContainerPtr getContainer(int index) { return m_containers[index]; }
|
||||||
@@ -340,6 +341,8 @@ private:
|
|||||||
std::bitset<Otc::LastGameFeature> m_features;
|
std::bitset<Otc::LastGameFeature> m_features;
|
||||||
ScheduledEventPtr m_pingEvent;
|
ScheduledEventPtr m_pingEvent;
|
||||||
ScheduledEventPtr m_walkEvent;
|
ScheduledEventPtr m_walkEvent;
|
||||||
|
ScheduledEventPtr m_checkConnectionEvent;
|
||||||
|
bool m_connectionFailWarned;
|
||||||
int m_protocolVersion;
|
int m_protocolVersion;
|
||||||
int m_clientVersion;
|
int m_clientVersion;
|
||||||
std::string m_clientSignature;
|
std::string m_clientSignature;
|
||||||
|
@@ -72,7 +72,7 @@ bool LocalPlayer::canWalk(Otc::Direction direction)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// last walk is not done yet
|
// last walk is not done yet
|
||||||
if(m_walkTimer.ticksElapsed() < getStepDuration())
|
if((m_walkTimer.ticksElapsed() < getStepDuration()) && !isAutoWalking())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// prewalk has a timeout, because for some reason that I don't know yet the server sometimes doesn't answer the prewalk
|
// prewalk has a timeout, because for some reason that I don't know yet the server sometimes doesn't answer the prewalk
|
||||||
@@ -83,7 +83,7 @@ bool LocalPlayer::canWalk(Otc::Direction direction)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// cannot walk while already walking
|
// cannot walk while already walking
|
||||||
if(m_walking && !prewalkTimeouted)
|
if((m_walking && !isAutoWalking()) && (!prewalkTimeouted || m_secondPreWalk))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -95,6 +95,7 @@ void LocalPlayer::walk(const Position& oldPos, const Position& newPos)
|
|||||||
if(m_preWalking) {
|
if(m_preWalking) {
|
||||||
// switch to normal walking
|
// switch to normal walking
|
||||||
m_preWalking = false;
|
m_preWalking = false;
|
||||||
|
m_secondPreWalk = false;
|
||||||
m_lastPrewalkDone = true;
|
m_lastPrewalkDone = true;
|
||||||
// if is to the last prewalk destination, updates the walk preserving the animation
|
// if is to the last prewalk destination, updates the walk preserving the animation
|
||||||
if(newPos == m_lastPrewalkDestination) {
|
if(newPos == m_lastPrewalkDestination) {
|
||||||
@@ -118,7 +119,8 @@ void LocalPlayer::preWalk(Otc::Direction direction)
|
|||||||
Position newPos = m_position.translatedToDirection(direction);
|
Position newPos = m_position.translatedToDirection(direction);
|
||||||
|
|
||||||
// avoid reanimating prewalks
|
// avoid reanimating prewalks
|
||||||
if(m_preWalking && m_lastPrewalkDestination == newPos) {
|
if(m_preWalking) {
|
||||||
|
m_secondPreWalk = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,6 +279,7 @@ void LocalPlayer::terminateWalk()
|
|||||||
{
|
{
|
||||||
Creature::terminateWalk();
|
Creature::terminateWalk();
|
||||||
m_preWalking = false;
|
m_preWalking = false;
|
||||||
|
m_secondPreWalk = false;
|
||||||
m_idleTimer.restart();
|
m_idleTimer.restart();
|
||||||
|
|
||||||
auto self = asLocalPlayer();
|
auto self = asLocalPlayer();
|
||||||
|
@@ -126,6 +126,7 @@ private:
|
|||||||
ticks_t m_walkLockExpiration;
|
ticks_t m_walkLockExpiration;
|
||||||
stdext::boolean<false> m_preWalking;
|
stdext::boolean<false> m_preWalking;
|
||||||
stdext::boolean<true> m_lastPrewalkDone;
|
stdext::boolean<true> m_lastPrewalkDone;
|
||||||
|
stdext::boolean<false> m_secondPreWalk;
|
||||||
stdext::boolean<false> m_serverWalking;
|
stdext::boolean<false> m_serverWalking;
|
||||||
stdext::boolean<false> m_knownCompletePath;
|
stdext::boolean<false> m_knownCompletePath;
|
||||||
|
|
||||||
|
@@ -230,6 +230,7 @@ void Client::registerLuaFunctions()
|
|||||||
g_lua.bindSingletonFunction("g_game", "isDead", &Game::isDead, &g_game);
|
g_lua.bindSingletonFunction("g_game", "isDead", &Game::isDead, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "isAttacking", &Game::isAttacking, &g_game);
|
g_lua.bindSingletonFunction("g_game", "isAttacking", &Game::isAttacking, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "isFollowing", &Game::isFollowing, &g_game);
|
g_lua.bindSingletonFunction("g_game", "isFollowing", &Game::isFollowing, &g_game);
|
||||||
|
g_lua.bindSingletonFunction("g_game", "isConnectionOk", &Game::isConnectionOk, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "getPing", &Game::getPing, &g_game);
|
g_lua.bindSingletonFunction("g_game", "getPing", &Game::getPing, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "getContainer", &Game::getContainer, &g_game);
|
g_lua.bindSingletonFunction("g_game", "getContainer", &Game::getContainer, &g_game);
|
||||||
g_lua.bindSingletonFunction("g_game", "getContainers", &Game::getContainers, &g_game);
|
g_lua.bindSingletonFunction("g_game", "getContainers", &Game::getContainers, &g_game);
|
||||||
|
@@ -608,21 +608,21 @@ int MapView::calcFirstVisibleFloor()
|
|||||||
Position pos = cameraPosition.translated(ix, iy);
|
Position pos = cameraPosition.translated(ix, iy);
|
||||||
|
|
||||||
// process tiles that we can look through, e.g. windows, doors
|
// process tiles that we can look through, e.g. windows, doors
|
||||||
if((ix == 0 && iy == 0) || (/*(std::abs(ix) != std::abs(iy)) && */g_map.isLookPossible(pos))) {
|
if((ix == 0 && iy == 0) || ((std::abs(ix) != std::abs(iy)) && g_map.isLookPossible(pos))) {
|
||||||
Position upperPos = pos;
|
Position upperPos = pos;
|
||||||
Position coveredPos = pos;
|
Position coveredPos = pos;
|
||||||
|
|
||||||
while(coveredPos.coveredUp() && upperPos.up() && upperPos.z >= firstFloor) {
|
while(coveredPos.coveredUp() && upperPos.up() && upperPos.z >= firstFloor) {
|
||||||
// check tiles physically above
|
// check tiles physically above
|
||||||
TilePtr tile = g_map.getTile(upperPos);
|
TilePtr tile = g_map.getTile(upperPos);
|
||||||
if(tile && tile->limitsFloorsView()) {
|
if(tile && tile->limitsFloorsView(!g_map.isLookPossible(pos))) {
|
||||||
firstFloor = upperPos.z + 1;
|
firstFloor = upperPos.z + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check tiles geometrically above
|
// check tiles geometrically above
|
||||||
tile = g_map.getTile(coveredPos);
|
tile = g_map.getTile(coveredPos);
|
||||||
if(tile && tile->limitsFloorsView()) {
|
if(tile && tile->limitsFloorsView(g_map.isLookPossible(pos))) {
|
||||||
firstFloor = coveredPos.z + 1;
|
firstFloor = coveredPos.z + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -603,6 +603,14 @@ void ProtocolGame::parseOpenContainer(const InputMessagePtr& msg)
|
|||||||
std::string name = msg->getString();
|
std::string name = msg->getString();
|
||||||
int capacity = msg->getU8();
|
int capacity = msg->getU8();
|
||||||
bool hasParent = (msg->getU8() != 0);
|
bool hasParent = (msg->getU8() != 0);
|
||||||
|
|
||||||
|
if(g_game.getFeature(Otc::GameContainerPagination)) {
|
||||||
|
msg->getU8(); // drag and drop
|
||||||
|
msg->getU8(); // pagination
|
||||||
|
msg->getU16(); // container size
|
||||||
|
msg->getU16(); // first index
|
||||||
|
}
|
||||||
|
|
||||||
int itemCount = msg->getU8();
|
int itemCount = msg->getU8();
|
||||||
|
|
||||||
std::vector<ItemPtr> items(itemCount);
|
std::vector<ItemPtr> items(itemCount);
|
||||||
@@ -622,13 +630,21 @@ void ProtocolGame::parseContainerAddItem(const InputMessagePtr& msg)
|
|||||||
{
|
{
|
||||||
int containerId = msg->getU8();
|
int containerId = msg->getU8();
|
||||||
ItemPtr item = getItem(msg);
|
ItemPtr item = getItem(msg);
|
||||||
|
if(g_game.getFeature(Otc::GameContainerPagination)) {
|
||||||
|
msg->getU16(); // slot
|
||||||
|
}
|
||||||
g_game.processContainerAddItem(containerId, item);
|
g_game.processContainerAddItem(containerId, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtocolGame::parseContainerUpdateItem(const InputMessagePtr& msg)
|
void ProtocolGame::parseContainerUpdateItem(const InputMessagePtr& msg)
|
||||||
{
|
{
|
||||||
int containerId = msg->getU8();
|
int containerId = msg->getU8();
|
||||||
int slot = msg->getU8();
|
int slot;
|
||||||
|
if(g_game.getFeature(Otc::GameContainerPagination)) {
|
||||||
|
slot = msg->getU16();
|
||||||
|
} else {
|
||||||
|
slot = msg->getU8();
|
||||||
|
}
|
||||||
ItemPtr item = getItem(msg);
|
ItemPtr item = getItem(msg);
|
||||||
g_game.processContainerUpdateItem(containerId, slot, item);
|
g_game.processContainerUpdateItem(containerId, slot, item);
|
||||||
}
|
}
|
||||||
@@ -636,7 +652,13 @@ void ProtocolGame::parseContainerUpdateItem(const InputMessagePtr& msg)
|
|||||||
void ProtocolGame::parseContainerRemoveItem(const InputMessagePtr& msg)
|
void ProtocolGame::parseContainerRemoveItem(const InputMessagePtr& msg)
|
||||||
{
|
{
|
||||||
int containerId = msg->getU8();
|
int containerId = msg->getU8();
|
||||||
int slot = msg->getU8();
|
int slot;
|
||||||
|
if(g_game.getFeature(Otc::GameContainerPagination)) {
|
||||||
|
slot = msg->getU16();
|
||||||
|
getItem(msg);
|
||||||
|
} else {
|
||||||
|
slot = msg->getU8();
|
||||||
|
}
|
||||||
g_game.processContainerRemoveItem(containerId, slot);
|
g_game.processContainerRemoveItem(containerId, slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1808,6 +1830,12 @@ CreaturePtr ProtocolGame::getCreature(const InputMessagePtr& msg, int type)
|
|||||||
if(g_game.getFeature(Otc::GameCreatureEmblems) && !known)
|
if(g_game.getFeature(Otc::GameCreatureEmblems) && !known)
|
||||||
emblem = msg->getU8();
|
emblem = msg->getU8();
|
||||||
|
|
||||||
|
if(g_game.getFeature(Otc::GameThingMarks)) {
|
||||||
|
msg->getU8(); // creature type for summons
|
||||||
|
msg->getU8(); // mark
|
||||||
|
msg->getU16(); // helpers
|
||||||
|
}
|
||||||
|
|
||||||
if(g_game.getProtocolVersion() >= 854)
|
if(g_game.getProtocolVersion() >= 854)
|
||||||
unpass = msg->getU8();
|
unpass = msg->getU8();
|
||||||
|
|
||||||
@@ -1860,6 +1888,10 @@ ItemPtr ProtocolGame::getItem(const InputMessagePtr& msg, int id)
|
|||||||
if(item->getId() == 0)
|
if(item->getId() == 0)
|
||||||
stdext::throw_exception(stdext::format("unable to create item with invalid id %d", id));
|
stdext::throw_exception(stdext::format("unable to create item with invalid id %d", id));
|
||||||
|
|
||||||
|
if(g_game.getFeature(Otc::GameThingMarks)) {
|
||||||
|
msg->getU8(); // mark
|
||||||
|
}
|
||||||
|
|
||||||
if(item->isStackable() || item->isFluidContainer() || item->isSplash() || item->isChargeable())
|
if(item->isStackable() || item->isFluidContainer() || item->isSplash() || item->isChargeable())
|
||||||
item->setCountOrSubType(msg->getU8());
|
item->setCountOrSubType(msg->getU8());
|
||||||
|
|
||||||
|
@@ -67,6 +67,17 @@ void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileS
|
|||||||
attr -= 1;
|
attr -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(g_game.getProtocolVersion() >= 1010) {
|
||||||
|
/* In 10.10 all attributes from 16 and up were
|
||||||
|
* incremented by 1 to make space for 16 as
|
||||||
|
* "No Movement Animation" flag.
|
||||||
|
*/
|
||||||
|
if(attr == 16)
|
||||||
|
attr = ThingAttrNoMoveAnimation;
|
||||||
|
else if(attr > 16)
|
||||||
|
attr -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
switch(attr) {
|
switch(attr) {
|
||||||
case ThingAttrDisplacement: {
|
case ThingAttrDisplacement: {
|
||||||
m_displacement.x = fin->getU16();
|
m_displacement.x = fin->getU16();
|
||||||
@@ -126,8 +137,8 @@ void ThingType::unserialize(uint16 clientId, ThingCategory category, const FileS
|
|||||||
|
|
||||||
int totalSprites = m_size.area() * m_layers * m_numPatternX * m_numPatternY * m_numPatternZ * m_animationPhases;
|
int totalSprites = m_size.area() * m_layers * m_numPatternX * m_numPatternY * m_numPatternZ * m_animationPhases;
|
||||||
|
|
||||||
if(totalSprites == 0)
|
// if(totalSprites == 0)
|
||||||
stdext::throw_exception("a thing type has no sprites");
|
// stdext::throw_exception("a thing type has no sprites");
|
||||||
if(totalSprites > 4096)
|
if(totalSprites > 4096)
|
||||||
stdext::throw_exception("a thing type has more than 4096 sprites");
|
stdext::throw_exception("a thing type has more than 4096 sprites");
|
||||||
|
|
||||||
|
@@ -81,6 +81,7 @@ enum ThingAttr : uint8 {
|
|||||||
ThingAttrOpacity = 100,
|
ThingAttrOpacity = 100,
|
||||||
ThingAttrNotPreWalkable = 101,
|
ThingAttrNotPreWalkable = 101,
|
||||||
|
|
||||||
|
ThingAttrNoMoveAnimation = 253, // real value is 16, but we need to do this for backwards compatibility
|
||||||
ThingAttrChargeable = 254, // deprecated
|
ThingAttrChargeable = 254, // deprecated
|
||||||
ThingLastAttr = 255
|
ThingLastAttr = 255
|
||||||
};
|
};
|
||||||
|
@@ -457,7 +457,7 @@ ThingPtr Tile::getTopMultiUseThing()
|
|||||||
if(thing->isForceUse())
|
if(thing->isForceUse())
|
||||||
return thing;
|
return thing;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(uint i = 0; i < m_things.size(); ++i) {
|
for(uint i = 0; i < m_things.size(); ++i) {
|
||||||
ThingPtr thing = m_things[i];
|
ThingPtr thing = m_things[i];
|
||||||
if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop()) {
|
if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom() && !thing->isOnTop()) {
|
||||||
@@ -590,15 +590,24 @@ bool Tile::hasCreature()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Tile::limitsFloorsView()
|
bool Tile::limitsFloorsView(bool isFreeView)
|
||||||
{
|
{
|
||||||
// ground and walls limits the view
|
// ground and walls limits the view
|
||||||
ThingPtr firstThing = getThing(0);
|
ThingPtr firstThing = getThing(0);
|
||||||
if(firstThing && !firstThing->isDontHide() && (firstThing->isGround() || firstThing->isOnBottom()))
|
|
||||||
return true;
|
if(isFreeView){
|
||||||
|
if(firstThing && !firstThing->isDontHide() && (firstThing->isGround() || firstThing->isOnBottom()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(firstThing && !firstThing->isDontHide() && (firstThing->isGround() || (firstThing->isOnBottom() && firstThing->blockProjectile())))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Tile::canErase()
|
bool Tile::canErase()
|
||||||
{
|
{
|
||||||
return m_walkingCreatures.empty() && m_effects.empty() && m_things.empty() && m_flags == 0 && m_minimapColor == 0;
|
return m_walkingCreatures.empty() && m_effects.empty() && m_things.empty() && m_flags == 0 && m_minimapColor == 0;
|
||||||
|
@@ -48,7 +48,7 @@ enum tileflags_t
|
|||||||
TILESTATE_TRASHHOLDER = 1 << 20,
|
TILESTATE_TRASHHOLDER = 1 << 20,
|
||||||
TILESTATE_BED = 1 << 21,
|
TILESTATE_BED = 1 << 21,
|
||||||
TILESTATE_DEPOT = 1 << 22,
|
TILESTATE_DEPOT = 1 << 22,
|
||||||
TILESTATE_TRANSLUECENT_LIGHT = 1 << 23
|
TILESTATE_TRANSLUECENT_LIGHT = 1 << 23
|
||||||
};
|
};
|
||||||
|
|
||||||
class Tile : public LuaObject
|
class Tile : public LuaObject
|
||||||
@@ -105,7 +105,7 @@ public:
|
|||||||
bool mustHookSouth();
|
bool mustHookSouth();
|
||||||
bool mustHookEast();
|
bool mustHookEast();
|
||||||
bool hasCreature();
|
bool hasCreature();
|
||||||
bool limitsFloorsView();
|
bool limitsFloorsView(bool isFreeView = false);
|
||||||
bool canErase();
|
bool canErase();
|
||||||
bool hasElevation(int elevation = 1);
|
bool hasElevation(int elevation = 1);
|
||||||
void overwriteMinimapColor(uint8 color) { m_minimapColor = color; }
|
void overwriteMinimapColor(uint8 color) { m_minimapColor = color; }
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#ifdef FW_GRAPHICS
|
#ifdef FW_GRAPHICS
|
||||||
#include <framework/platform/platformwindow.h>
|
#include <framework/platform/platformwindow.h>
|
||||||
|
#include <framework/platform/platform.h>
|
||||||
#include <framework/luaengine/luainterface.h>
|
#include <framework/luaengine/luainterface.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -104,16 +105,16 @@ void Logger::logFunc(Fw::LogLevel level, const std::string& message, std::string
|
|||||||
prettyFunction = prettyFunction.substr(prettyFunction.find_last_of(' ') + 1);
|
prettyFunction = prettyFunction.substr(prettyFunction.find_last_of(' ') + 1);
|
||||||
|
|
||||||
|
|
||||||
std::string out = message;
|
std::stringstream ss;
|
||||||
|
ss << message;
|
||||||
|
|
||||||
if(!prettyFunction.empty()) {
|
if(!prettyFunction.empty()) {
|
||||||
if(g_lua.isInCppCallback())
|
if(g_lua.isInCppCallback())
|
||||||
out = g_lua.traceback(out, 1);
|
ss << g_lua.traceback("", 1);
|
||||||
else
|
ss << g_platform.traceback(prettyFunction, 1, 8);
|
||||||
out += "\nat:\t[C++]: " + prettyFunction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log(level, out);
|
log(level, ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::fireOldMessages()
|
void Logger::fireOldMessages()
|
||||||
|
@@ -577,20 +577,19 @@ int LuaInterface::lua_dofile(lua_State* L)
|
|||||||
|
|
||||||
int LuaInterface::lua_dofiles(lua_State* L)
|
int LuaInterface::lua_dofiles(lua_State* L)
|
||||||
{
|
{
|
||||||
std::string directory = g_lua.popString();
|
std::string contains = "";
|
||||||
|
if(g_lua.getTop() > 2) {
|
||||||
for(const std::string& fileName : g_resources.listDirectoryFiles(directory)) {
|
contains = g_lua.popString();
|
||||||
if(!g_resources.isFileType(fileName, "lua"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
try {
|
|
||||||
g_lua.loadScript(directory + "/" + fileName);
|
|
||||||
g_lua.call(0, 0);
|
|
||||||
} catch(stdext::exception& e) {
|
|
||||||
g_lua.pushString(e.what());
|
|
||||||
g_lua.error();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool recursive = false;
|
||||||
|
if(g_lua.getTop() > 1) {
|
||||||
|
recursive = g_lua.popBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string directory = g_lua.popString();
|
||||||
|
g_lua.loadFiles(directory, recursive, contains);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1247,3 +1246,29 @@ int LuaInterface::getTop()
|
|||||||
{
|
{
|
||||||
return lua_gettop(L);
|
return lua_gettop(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LuaInterface::loadFiles(std::string directory, bool recursive, std::string contains)
|
||||||
|
{
|
||||||
|
for(const std::string& fileName : g_resources.listDirectoryFiles(directory)) {
|
||||||
|
std::string fullPath = directory + "/" + fileName;
|
||||||
|
|
||||||
|
if(recursive && g_resources.directoryExists(fullPath)) {
|
||||||
|
loadFiles(fullPath, true, contains);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!g_resources.isFileType(fileName, "lua"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(!contains.empty() && fileName.find(contains) == std::string::npos)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
try {
|
||||||
|
g_lua.loadScript(fullPath);
|
||||||
|
g_lua.call(0, 0);
|
||||||
|
} catch(stdext::exception& e) {
|
||||||
|
g_lua.pushString(e.what());
|
||||||
|
g_lua.error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -321,6 +321,8 @@ public:
|
|||||||
void clearStack() { pop(stackSize()); }
|
void clearStack() { pop(stackSize()); }
|
||||||
bool hasIndex(int index) { return (stackSize() >= (index < 0 ? -index : index) && index != 0); }
|
bool hasIndex(int index) { return (stackSize() >= (index < 0 ? -index : index) && index != 0); }
|
||||||
|
|
||||||
|
void loadFiles(std::string directory, bool recursive = false, std::string contains = "");
|
||||||
|
|
||||||
/// Pushes any type onto the stack
|
/// Pushes any type onto the stack
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
int polymorphicPush(const T& v, const Args&... args);
|
int polymorphicPush(const T& v, const Args&... args);
|
||||||
|
@@ -569,6 +569,7 @@ void Application::registerLuaFunctions()
|
|||||||
g_lua.bindClassMemberFunction<UIWidget>("setImageFixedRatio", &UIWidget::setImageFixedRatio);
|
g_lua.bindClassMemberFunction<UIWidget>("setImageFixedRatio", &UIWidget::setImageFixedRatio);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("setImageRepeated", &UIWidget::setImageRepeated);
|
g_lua.bindClassMemberFunction<UIWidget>("setImageRepeated", &UIWidget::setImageRepeated);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("setImageSmooth", &UIWidget::setImageSmooth);
|
g_lua.bindClassMemberFunction<UIWidget>("setImageSmooth", &UIWidget::setImageSmooth);
|
||||||
|
g_lua.bindClassMemberFunction<UIWidget>("setImageAutoResize", &UIWidget::setImageAutoResize);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("setImageBorderTop", &UIWidget::setImageBorderTop);
|
g_lua.bindClassMemberFunction<UIWidget>("setImageBorderTop", &UIWidget::setImageBorderTop);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("setImageBorderRight", &UIWidget::setImageBorderRight);
|
g_lua.bindClassMemberFunction<UIWidget>("setImageBorderRight", &UIWidget::setImageBorderRight);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("setImageBorderBottom", &UIWidget::setImageBorderBottom);
|
g_lua.bindClassMemberFunction<UIWidget>("setImageBorderBottom", &UIWidget::setImageBorderBottom);
|
||||||
@@ -585,6 +586,7 @@ void Application::registerLuaFunctions()
|
|||||||
g_lua.bindClassMemberFunction<UIWidget>("getImageColor", &UIWidget::getImageColor);
|
g_lua.bindClassMemberFunction<UIWidget>("getImageColor", &UIWidget::getImageColor);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("isImageFixedRatio", &UIWidget::isImageFixedRatio);
|
g_lua.bindClassMemberFunction<UIWidget>("isImageFixedRatio", &UIWidget::isImageFixedRatio);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("isImageSmooth", &UIWidget::isImageSmooth);
|
g_lua.bindClassMemberFunction<UIWidget>("isImageSmooth", &UIWidget::isImageSmooth);
|
||||||
|
g_lua.bindClassMemberFunction<UIWidget>("isImageAutoResize", &UIWidget::isImageAutoResize);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("getImageBorderTop", &UIWidget::getImageBorderTop);
|
g_lua.bindClassMemberFunction<UIWidget>("getImageBorderTop", &UIWidget::getImageBorderTop);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("getImageBorderRight", &UIWidget::getImageBorderRight);
|
g_lua.bindClassMemberFunction<UIWidget>("getImageBorderRight", &UIWidget::getImageBorderRight);
|
||||||
g_lua.bindClassMemberFunction<UIWidget>("getImageBorderBottom", &UIWidget::getImageBorderBottom);
|
g_lua.bindClassMemberFunction<UIWidget>("getImageBorderBottom", &UIWidget::getImageBorderBottom);
|
||||||
|
@@ -27,16 +27,17 @@
|
|||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
|
|
||||||
asio::io_service g_ioService;
|
asio::io_service g_ioService;
|
||||||
|
std::list<std::shared_ptr<asio::streambuf>> Connection::m_outputStreams;
|
||||||
|
|
||||||
Connection::Connection() :
|
Connection::Connection() :
|
||||||
m_readTimer(g_ioService),
|
m_readTimer(g_ioService),
|
||||||
m_writeTimer(g_ioService),
|
m_writeTimer(g_ioService),
|
||||||
|
m_delayedWriteTimer(g_ioService),
|
||||||
m_resolver(g_ioService),
|
m_resolver(g_ioService),
|
||||||
m_socket(g_ioService)
|
m_socket(g_ioService)
|
||||||
{
|
{
|
||||||
m_connected = false;
|
m_connected = false;
|
||||||
m_connecting = false;
|
m_connecting = false;
|
||||||
m_sendBufferSize = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::~Connection()
|
Connection::~Connection()
|
||||||
@@ -56,34 +57,7 @@ void Connection::poll()
|
|||||||
void Connection::terminate()
|
void Connection::terminate()
|
||||||
{
|
{
|
||||||
g_ioService.stop();
|
g_ioService.stop();
|
||||||
}
|
m_outputStreams.clear();
|
||||||
|
|
||||||
void Connection::connect(const std::string& host, uint16 port, const std::function<void()>& connectCallback)
|
|
||||||
{
|
|
||||||
m_connected = false;
|
|
||||||
m_connecting = true;
|
|
||||||
m_error.clear();
|
|
||||||
m_connectCallback = connectCallback;
|
|
||||||
|
|
||||||
asio::ip::tcp::resolver::query query(host, stdext::unsafe_cast<std::string>(port));
|
|
||||||
|
|
||||||
auto self = asConnection();
|
|
||||||
m_resolver.async_resolve(query, [=](const boost::system::error_code& error, asio::ip::tcp::resolver::iterator endpointIterator) {
|
|
||||||
if(self.is_unique())
|
|
||||||
return;
|
|
||||||
m_readTimer.cancel();
|
|
||||||
|
|
||||||
if(!error) {
|
|
||||||
m_socket.async_connect(*endpointIterator, std::bind(&Connection::onConnect, asConnection(), std::placeholders::_1));
|
|
||||||
|
|
||||||
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
|
||||||
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
|
||||||
} else
|
|
||||||
handleError(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
|
||||||
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::close()
|
void Connection::close()
|
||||||
@@ -92,8 +66,8 @@ void Connection::close()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// flush send data before disconnecting on clean connections
|
// flush send data before disconnecting on clean connections
|
||||||
if(m_connected && !m_error && m_sendBufferSize > 0 && m_sendEvent)
|
if(m_connected && !m_error && m_outputStream)
|
||||||
m_sendEvent->execute();
|
internal_write();
|
||||||
|
|
||||||
m_connecting = false;
|
m_connecting = false;
|
||||||
m_connected = false;
|
m_connected = false;
|
||||||
@@ -104,6 +78,7 @@ void Connection::close()
|
|||||||
m_resolver.cancel();
|
m_resolver.cancel();
|
||||||
m_readTimer.cancel();
|
m_readTimer.cancel();
|
||||||
m_writeTimer.cancel();
|
m_writeTimer.cancel();
|
||||||
|
m_delayedWriteTimer.cancel();
|
||||||
|
|
||||||
if(m_socket.is_open()) {
|
if(m_socket.is_open()) {
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
@@ -112,94 +87,138 @@ void Connection::close()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::write(uint8* buffer, uint16 size)
|
void Connection::connect(const std::string& host, uint16 port, const std::function<void()>& connectCallback)
|
||||||
|
{
|
||||||
|
m_connected = false;
|
||||||
|
m_connecting = true;
|
||||||
|
m_error.clear();
|
||||||
|
m_connectCallback = connectCallback;
|
||||||
|
|
||||||
|
asio::ip::tcp::resolver::query query(host, stdext::unsafe_cast<std::string>(port));
|
||||||
|
m_resolver.async_resolve(query, std::bind(&Connection::onResolve, asConnection(), std::placeholders::_1, std::placeholders::_2));
|
||||||
|
|
||||||
|
m_readTimer.cancel();
|
||||||
|
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
||||||
|
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::internal_connect(asio::ip::basic_resolver<asio::ip::tcp>::iterator endpointIterator)
|
||||||
|
{
|
||||||
|
m_socket.async_connect(*endpointIterator, std::bind(&Connection::onConnect, asConnection(), std::placeholders::_1));
|
||||||
|
|
||||||
|
m_readTimer.cancel();
|
||||||
|
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
||||||
|
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::write(uint8* buffer, size_t size)
|
||||||
{
|
{
|
||||||
if(!m_connected)
|
if(!m_connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// send old buffer if we can't add more data
|
|
||||||
if(m_sendBufferSize + size >= SEND_BUFFER_SIZE && m_sendEvent)
|
|
||||||
m_sendEvent->execute();
|
|
||||||
|
|
||||||
// we can't send the data right away, otherwise we could create tcp congestion
|
// we can't send the data right away, otherwise we could create tcp congestion
|
||||||
memcpy(m_sendBuffer + m_sendBufferSize, buffer, size);
|
if(!m_outputStream) {
|
||||||
m_sendBufferSize += size;
|
if(!m_outputStreams.empty()) {
|
||||||
|
m_outputStream = m_outputStreams.front();
|
||||||
|
m_outputStreams.pop_front();
|
||||||
|
} else
|
||||||
|
m_outputStream = std::shared_ptr<asio::streambuf>(new asio::streambuf);
|
||||||
|
|
||||||
if(!m_sendEvent || m_sendEvent->isExecuted() || m_sendEvent->isCanceled()) {
|
m_delayedWriteTimer.cancel();
|
||||||
auto self = asConnection();
|
m_delayedWriteTimer.expires_from_now(boost::posix_time::milliseconds(10));
|
||||||
|
m_delayedWriteTimer.async_wait(std::bind(&Connection::onCanWrite, asConnection(), std::placeholders::_1));
|
||||||
// wait 1 ms to do the real send
|
|
||||||
m_sendEvent = g_dispatcher.scheduleEvent([=] {
|
|
||||||
if(self.is_unique())
|
|
||||||
return;
|
|
||||||
//m_writeTimer.cancel();
|
|
||||||
|
|
||||||
asio::async_write(m_socket,
|
|
||||||
asio::buffer(m_sendBuffer, m_sendBufferSize),
|
|
||||||
std::bind(&Connection::onWrite, asConnection(), std::placeholders::_1, std::placeholders::_2));
|
|
||||||
|
|
||||||
m_writeTimer.expires_from_now(boost::posix_time::seconds(WRITE_TIMEOUT));
|
|
||||||
m_writeTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
|
||||||
|
|
||||||
m_sendBufferSize = 0;
|
|
||||||
}, SEND_INTERVAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream os(m_outputStream.get());
|
||||||
|
os.write((const char*)buffer, size);
|
||||||
|
os.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::internal_write()
|
||||||
|
{
|
||||||
|
if(!m_connected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::shared_ptr<asio::streambuf> outputStream = m_outputStream;
|
||||||
|
m_outputStream = nullptr;
|
||||||
|
|
||||||
|
asio::async_write(m_socket,
|
||||||
|
*outputStream,
|
||||||
|
std::bind(&Connection::onWrite, asConnection(), std::placeholders::_1, std::placeholders::_2, outputStream));
|
||||||
|
|
||||||
|
m_writeTimer.cancel();
|
||||||
|
m_writeTimer.expires_from_now(boost::posix_time::seconds(WRITE_TIMEOUT));
|
||||||
|
m_writeTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::read(uint16 bytes, const RecvCallback& callback)
|
void Connection::read(uint16 bytes, const RecvCallback& callback)
|
||||||
{
|
{
|
||||||
m_readTimer.cancel();
|
|
||||||
|
|
||||||
if(!m_connected)
|
if(!m_connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_recvCallback = callback;
|
m_recvCallback = callback;
|
||||||
|
|
||||||
asio::async_read(m_socket,
|
asio::async_read(m_socket,
|
||||||
asio::buffer(m_streamBuffer.prepare(bytes)),
|
asio::buffer(m_inputStream.prepare(bytes)),
|
||||||
std::bind(&Connection::onRecv, asConnection(), std::placeholders::_1, bytes));
|
std::bind(&Connection::onRecv, asConnection(), std::placeholders::_1, std::placeholders::_2));
|
||||||
|
|
||||||
|
m_readTimer.cancel();
|
||||||
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
||||||
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::read_until(const std::string& what, const RecvCallback& callback)
|
void Connection::read_until(const std::string& what, const RecvCallback& callback)
|
||||||
{
|
{
|
||||||
m_readTimer.cancel();
|
|
||||||
|
|
||||||
if(!m_connected)
|
if(!m_connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_recvCallback = callback;
|
m_recvCallback = callback;
|
||||||
|
|
||||||
asio::async_read_until(m_socket,
|
asio::async_read_until(m_socket,
|
||||||
m_streamBuffer,
|
m_inputStream,
|
||||||
what.c_str(),
|
what.c_str(),
|
||||||
std::bind(&Connection::onRecv, asConnection(), std::placeholders::_1, std::placeholders::_2));
|
std::bind(&Connection::onRecv, asConnection(), std::placeholders::_1, std::placeholders::_2));
|
||||||
|
|
||||||
|
m_readTimer.cancel();
|
||||||
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
||||||
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::read_some(const RecvCallback& callback)
|
void Connection::read_some(const RecvCallback& callback)
|
||||||
{
|
{
|
||||||
m_readTimer.cancel();
|
|
||||||
|
|
||||||
if(!m_connected)
|
if(!m_connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_recvCallback = callback;
|
m_recvCallback = callback;
|
||||||
|
|
||||||
m_socket.async_read_some(asio::buffer(m_streamBuffer.prepare(RECV_BUFFER_SIZE)),
|
m_socket.async_read_some(asio::buffer(m_inputStream.prepare(RECV_BUFFER_SIZE)),
|
||||||
std::bind(&Connection::onRecv, asConnection(), std::placeholders::_1, std::placeholders::_2));
|
std::bind(&Connection::onRecv, asConnection(), std::placeholders::_1, std::placeholders::_2));
|
||||||
|
|
||||||
|
m_readTimer.cancel();
|
||||||
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
m_readTimer.expires_from_now(boost::posix_time::seconds(READ_TIMEOUT));
|
||||||
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
m_readTimer.async_wait(std::bind(&Connection::onTimeout, asConnection(), std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Connection::onResolve(const boost::system::error_code& error, asio::ip::basic_resolver<asio::ip::tcp>::iterator endpointIterator)
|
||||||
|
{
|
||||||
|
m_readTimer.cancel();
|
||||||
|
|
||||||
|
if(error == asio::error::operation_aborted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!error)
|
||||||
|
internal_connect(endpointIterator);
|
||||||
|
else
|
||||||
|
handleError(error);
|
||||||
|
}
|
||||||
|
|
||||||
void Connection::onConnect(const boost::system::error_code& error)
|
void Connection::onConnect(const boost::system::error_code& error)
|
||||||
{
|
{
|
||||||
m_readTimer.cancel();
|
m_readTimer.cancel();
|
||||||
|
m_activityTimer.restart();
|
||||||
|
|
||||||
|
if(error == asio::error::operation_aborted)
|
||||||
|
return;
|
||||||
|
|
||||||
if(!error) {
|
if(!error) {
|
||||||
m_connected = true;
|
m_connected = true;
|
||||||
@@ -216,51 +235,72 @@ void Connection::onConnect(const boost::system::error_code& error)
|
|||||||
m_connecting = false;
|
m_connecting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::onWrite(const boost::system::error_code& error, size_t)
|
void Connection::onCanWrite(const boost::system::error_code& error)
|
||||||
|
{
|
||||||
|
m_delayedWriteTimer.cancel();
|
||||||
|
|
||||||
|
if(error == asio::error::operation_aborted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(m_connected)
|
||||||
|
internal_write();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::onWrite(const boost::system::error_code& error, size_t writeSize, std::shared_ptr<asio::streambuf> outputStream)
|
||||||
{
|
{
|
||||||
m_writeTimer.cancel();
|
m_writeTimer.cancel();
|
||||||
|
|
||||||
if(!m_connected)
|
if(error == asio::error::operation_aborted)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(error)
|
// free output stream and store for using it again later
|
||||||
|
outputStream->consume(outputStream->size());
|
||||||
|
m_outputStreams.push_back(outputStream);
|
||||||
|
|
||||||
|
if(m_connected && error)
|
||||||
handleError(error);
|
handleError(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::onRecv(const boost::system::error_code& error, size_t recvSize)
|
void Connection::onRecv(const boost::system::error_code& error, size_t recvSize)
|
||||||
{
|
{
|
||||||
m_readTimer.cancel();
|
m_readTimer.cancel();
|
||||||
|
m_activityTimer.restart();
|
||||||
|
|
||||||
if(!m_connected)
|
if(error == asio::error::operation_aborted)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(!error) {
|
if(m_connected) {
|
||||||
if(m_recvCallback) {
|
if(!error) {
|
||||||
const char* header = boost::asio::buffer_cast<const char*>(m_streamBuffer.data());
|
if(m_recvCallback) {
|
||||||
m_recvCallback((uint8*)header, recvSize);
|
const char* header = boost::asio::buffer_cast<const char*>(m_inputStream.data());
|
||||||
}
|
m_recvCallback((uint8*)header, recvSize);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
handleError(error);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
handleError(error);
|
|
||||||
|
|
||||||
m_streamBuffer.consume(recvSize);
|
if(!error)
|
||||||
|
m_inputStream.consume(recvSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::onTimeout(const boost::system::error_code& error)
|
void Connection::onTimeout(const boost::system::error_code& error)
|
||||||
{
|
{
|
||||||
if(error != asio::error::operation_aborted)
|
if(error == asio::error::operation_aborted)
|
||||||
handleError(asio::error::timed_out);
|
return;
|
||||||
|
|
||||||
|
handleError(asio::error::timed_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::handleError(const boost::system::error_code& error)
|
void Connection::handleError(const boost::system::error_code& error)
|
||||||
{
|
{
|
||||||
if(error != asio::error::operation_aborted) {
|
if(error == asio::error::operation_aborted)
|
||||||
m_error = error;
|
return;
|
||||||
if(m_errorCallback)
|
|
||||||
m_errorCallback(error);
|
m_error = error;
|
||||||
if(m_connected || m_connecting)
|
if(m_errorCallback)
|
||||||
close();
|
m_errorCallback(error);
|
||||||
}
|
if(m_connected || m_connecting)
|
||||||
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Connection::getIp()
|
int Connection::getIp()
|
||||||
|
@@ -36,7 +36,6 @@ class Connection : public LuaObject
|
|||||||
enum {
|
enum {
|
||||||
READ_TIMEOUT = 30,
|
READ_TIMEOUT = 30,
|
||||||
WRITE_TIMEOUT = 30,
|
WRITE_TIMEOUT = 30,
|
||||||
SEND_INTERVAL = 1,
|
|
||||||
SEND_BUFFER_SIZE = 65536,
|
SEND_BUFFER_SIZE = 65536,
|
||||||
RECV_BUFFER_SIZE = 65536
|
RECV_BUFFER_SIZE = 65536
|
||||||
};
|
};
|
||||||
@@ -51,7 +50,7 @@ public:
|
|||||||
void connect(const std::string& host, uint16 port, const std::function<void()>& connectCallback);
|
void connect(const std::string& host, uint16 port, const std::function<void()>& connectCallback);
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
void write(uint8* buffer, uint16 size);
|
void write(uint8* buffer, size_t size);
|
||||||
void read(uint16 bytes, const RecvCallback& callback);
|
void read(uint16 bytes, const RecvCallback& callback);
|
||||||
void read_until(const std::string& what, const RecvCallback& callback);
|
void read_until(const std::string& what, const RecvCallback& callback);
|
||||||
void read_some(const RecvCallback& callback);
|
void read_some(const RecvCallback& callback);
|
||||||
@@ -62,11 +61,17 @@ public:
|
|||||||
boost::system::error_code getError() { return m_error; }
|
boost::system::error_code getError() { return m_error; }
|
||||||
bool isConnecting() { return m_connecting; }
|
bool isConnecting() { return m_connecting; }
|
||||||
bool isConnected() { return m_connected; }
|
bool isConnected() { return m_connected; }
|
||||||
|
ticks_t getElapsedTicksSinceLastRead() { return m_connected ? m_activityTimer.elapsed_millis() : -1; }
|
||||||
|
|
||||||
ConnectionPtr asConnection() { return static_self_cast<Connection>(); }
|
ConnectionPtr asConnection() { return static_self_cast<Connection>(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void internal_connect(asio::ip::basic_resolver<asio::ip::tcp>::iterator endpointIterator);
|
||||||
|
void internal_write();
|
||||||
|
void onResolve(const boost::system::error_code& error, asio::ip::tcp::resolver::iterator endpointIterator);
|
||||||
void onConnect(const boost::system::error_code& error);
|
void onConnect(const boost::system::error_code& error);
|
||||||
void onWrite(const boost::system::error_code& error, size_t);
|
void onCanWrite(const boost::system::error_code& error);
|
||||||
|
void onWrite(const boost::system::error_code& error, size_t writeSize, std::shared_ptr<asio::streambuf> outputStream);
|
||||||
void onRecv(const boost::system::error_code& error, size_t recvSize);
|
void onRecv(const boost::system::error_code& error, size_t recvSize);
|
||||||
void onTimeout(const boost::system::error_code& error);
|
void onTimeout(const boost::system::error_code& error);
|
||||||
void handleError(const boost::system::error_code& error);
|
void handleError(const boost::system::error_code& error);
|
||||||
@@ -77,17 +82,17 @@ protected:
|
|||||||
|
|
||||||
asio::deadline_timer m_readTimer;
|
asio::deadline_timer m_readTimer;
|
||||||
asio::deadline_timer m_writeTimer;
|
asio::deadline_timer m_writeTimer;
|
||||||
|
asio::deadline_timer m_delayedWriteTimer;
|
||||||
asio::ip::tcp::resolver m_resolver;
|
asio::ip::tcp::resolver m_resolver;
|
||||||
asio::ip::tcp::socket m_socket;
|
asio::ip::tcp::socket m_socket;
|
||||||
|
|
||||||
uint8 m_sendBuffer[SEND_BUFFER_SIZE];
|
static std::list<std::shared_ptr<asio::streambuf>> m_outputStreams;
|
||||||
asio::streambuf m_streamBuffer;
|
std::shared_ptr<asio::streambuf> m_outputStream;
|
||||||
|
asio::streambuf m_inputStream;
|
||||||
bool m_connected;
|
bool m_connected;
|
||||||
bool m_connecting;
|
bool m_connecting;
|
||||||
boost::system::error_code m_error;
|
boost::system::error_code m_error;
|
||||||
int m_sendBufferSize;
|
stdext::timer m_activityTimer;
|
||||||
Timer m_sendTimer;
|
|
||||||
ScheduledEventPtr m_sendEvent;
|
|
||||||
|
|
||||||
friend class Server;
|
friend class Server;
|
||||||
};
|
};
|
||||||
|
@@ -42,6 +42,8 @@ public:
|
|||||||
|
|
||||||
bool isConnected();
|
bool isConnected();
|
||||||
bool isConnecting();
|
bool isConnecting();
|
||||||
|
ticks_t getElapsedTicksSinceLastRead() { return m_connection ? m_connection->getElapsedTicksSinceLastRead() : -1; }
|
||||||
|
|
||||||
ConnectionPtr getConnection() { return m_connection; }
|
ConnectionPtr getConnection() { return m_connection; }
|
||||||
void setConnection(const ConnectionPtr& connection) { m_connection = connection; }
|
void setConnection(const ConnectionPtr& connection) { m_connection = connection; }
|
||||||
|
|
||||||
|
@@ -45,6 +45,7 @@ public:
|
|||||||
std::string getCPUName();
|
std::string getCPUName();
|
||||||
double getTotalSystemMemory();
|
double getTotalSystemMemory();
|
||||||
std::string getOSName();
|
std::string getOSName();
|
||||||
|
std::string traceback(const std::string& where, int level = 1, int maxDepth = 32);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Platform g_platform;
|
extern Platform g_platform;
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
#include <framework/stdext/stdext.h>
|
#include <framework/stdext/stdext.h>
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <execinfo.h>
|
||||||
|
|
||||||
void Platform::processArgs(std::vector<std::string>& args)
|
void Platform::processArgs(std::vector<std::string>& args)
|
||||||
{
|
{
|
||||||
@@ -168,5 +169,35 @@ std::string Platform::getOSName()
|
|||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Platform::traceback(const std::string& where, int level, int maxDepth)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
|
ss << "\nC++ stack traceback:";
|
||||||
|
if(!where.empty())
|
||||||
|
ss << "\n\t[C++]: " << where;
|
||||||
|
|
||||||
|
void* buffer[maxDepth + level + 1];
|
||||||
|
int numLevels = backtrace(buffer, maxDepth + level + 1);
|
||||||
|
char **tracebackBuffer = backtrace_symbols(buffer, numLevels);
|
||||||
|
if(tracebackBuffer) {
|
||||||
|
for(int i = 1 + level; i < numLevels; i++) {
|
||||||
|
std::string line = tracebackBuffer[i];
|
||||||
|
if(line.find("__libc_start_main") != std::string::npos)
|
||||||
|
break;
|
||||||
|
std::size_t demanglePos = line.find("(_Z");
|
||||||
|
if(demanglePos != std::string::npos) {
|
||||||
|
demanglePos++;
|
||||||
|
int len = std::min(line.find_first_of("+", demanglePos), line.find_first_of(")", demanglePos)) - demanglePos;
|
||||||
|
std::string funcName = line.substr(demanglePos, len);
|
||||||
|
line.replace(demanglePos, len, stdext::demangle_name(funcName.c_str()));
|
||||||
|
}
|
||||||
|
ss << "\n\t" << line;
|
||||||
|
}
|
||||||
|
free(tracebackBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -414,4 +414,13 @@ std::string Platform::getOSName()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string Platform::traceback(const std::string& where, int level, int maxDepth)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "\nat:";
|
||||||
|
ss << "\n\t[C++]: " << where;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -624,6 +624,9 @@ LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_SYSKEYDOWN: {
|
case WM_SYSKEYDOWN: {
|
||||||
|
if(wParam == VK_F4 && m_inputEvent.keyboardModifiers & Fw::KeyboardAltModifier)
|
||||||
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||||
|
|
||||||
processKeyDown(retranslateVirtualKey(wParam, lParam));
|
processKeyDown(retranslateVirtualKey(wParam, lParam));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -26,7 +26,7 @@
|
|||||||
#include <boost/thread/future.hpp>
|
#include <boost/thread/future.hpp>
|
||||||
|
|
||||||
// hack to enable std::thread on mingw32 4.6
|
// hack to enable std::thread on mingw32 4.6
|
||||||
#if !defined(_GLIBCXX_HAS_GTHREADS) && defined(__GNUG__)
|
#if !defined(_GLIBCXX_HAS_GTHREADS) && defined(__GNUG__) && !defined(__clang__)
|
||||||
|
|
||||||
#include <boost/thread/thread.hpp>
|
#include <boost/thread/thread.hpp>
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
|
@@ -98,9 +98,9 @@ void UIWidget::drawSelf(Fw::DrawPane drawPane)
|
|||||||
}
|
}
|
||||||
|
|
||||||
drawImage(m_rect);
|
drawImage(m_rect);
|
||||||
drawBorder(m_rect);
|
|
||||||
drawIcon(m_rect);
|
drawIcon(m_rect);
|
||||||
drawText(m_rect);
|
drawText(m_rect);
|
||||||
|
drawBorder(m_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIWidget::drawChildren(const Rect& visibleRect, Fw::DrawPane drawPane)
|
void UIWidget::drawChildren(const Rect& visibleRect, Fw::DrawPane drawPane)
|
||||||
|
@@ -419,6 +419,7 @@ protected:
|
|||||||
stdext::boolean<false> m_imageFixedRatio;
|
stdext::boolean<false> m_imageFixedRatio;
|
||||||
stdext::boolean<false> m_imageRepeated;
|
stdext::boolean<false> m_imageRepeated;
|
||||||
stdext::boolean<false> m_imageSmooth;
|
stdext::boolean<false> m_imageSmooth;
|
||||||
|
stdext::boolean<false> m_imageAutoResize;
|
||||||
EdgeGroup<int> m_imageBorder;
|
EdgeGroup<int> m_imageBorder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -435,6 +436,7 @@ public:
|
|||||||
void setImageFixedRatio(bool fixedRatio) { m_imageFixedRatio = fixedRatio; updateImageCache(); }
|
void setImageFixedRatio(bool fixedRatio) { m_imageFixedRatio = fixedRatio; updateImageCache(); }
|
||||||
void setImageRepeated(bool repeated) { m_imageRepeated = repeated; updateImageCache(); }
|
void setImageRepeated(bool repeated) { m_imageRepeated = repeated; updateImageCache(); }
|
||||||
void setImageSmooth(bool smooth) { m_imageSmooth = smooth; }
|
void setImageSmooth(bool smooth) { m_imageSmooth = smooth; }
|
||||||
|
void setImageAutoResize(bool autoResize) { m_imageAutoResize = autoResize; }
|
||||||
void setImageBorderTop(int border) { m_imageBorder.top = border; configureBorderImage(); }
|
void setImageBorderTop(int border) { m_imageBorder.top = border; configureBorderImage(); }
|
||||||
void setImageBorderRight(int border) { m_imageBorder.right = border; configureBorderImage(); }
|
void setImageBorderRight(int border) { m_imageBorder.right = border; configureBorderImage(); }
|
||||||
void setImageBorderBottom(int border) { m_imageBorder.bottom = border; configureBorderImage(); }
|
void setImageBorderBottom(int border) { m_imageBorder.bottom = border; configureBorderImage(); }
|
||||||
@@ -452,6 +454,7 @@ public:
|
|||||||
Color getImageColor() { return m_imageColor; }
|
Color getImageColor() { return m_imageColor; }
|
||||||
bool isImageFixedRatio() { return m_imageFixedRatio; }
|
bool isImageFixedRatio() { return m_imageFixedRatio; }
|
||||||
bool isImageSmooth() { return m_imageSmooth; }
|
bool isImageSmooth() { return m_imageSmooth; }
|
||||||
|
bool isImageAutoResize() { return m_imageAutoResize; }
|
||||||
int getImageBorderTop() { return m_imageBorder.top; }
|
int getImageBorderTop() { return m_imageBorder.top; }
|
||||||
int getImageBorderRight() { return m_imageBorder.right; }
|
int getImageBorderRight() { return m_imageBorder.right; }
|
||||||
int getImageBorderBottom() { return m_imageBorder.bottom; }
|
int getImageBorderBottom() { return m_imageBorder.bottom; }
|
||||||
|
@@ -68,9 +68,10 @@ void UIWidget::parseImageStyle(const OTMLNodePtr& styleNode)
|
|||||||
setImageBorderBottom(node->value<int>());
|
setImageBorderBottom(node->value<int>());
|
||||||
else if(node->tag() == "image-border-left")
|
else if(node->tag() == "image-border-left")
|
||||||
setImageBorderLeft(node->value<int>());
|
setImageBorderLeft(node->value<int>());
|
||||||
else if(node->tag() == "image-border") {
|
else if(node->tag() == "image-border")
|
||||||
setImageBorder(node->value<int>());
|
setImageBorder(node->value<int>());
|
||||||
}
|
else if(node->tag() == "image-auto-resize")
|
||||||
|
setImageAutoResize(node->value<bool>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,5 +181,16 @@ void UIWidget::setImageSource(const std::string& source)
|
|||||||
m_imageTexture = nullptr;
|
m_imageTexture = nullptr;
|
||||||
else
|
else
|
||||||
m_imageTexture = g_textures.getTexture(source);
|
m_imageTexture = g_textures.getTexture(source);
|
||||||
|
|
||||||
|
if(m_imageTexture && (!m_rect.isValid() || m_imageAutoResize)) {
|
||||||
|
Size size = getSize();
|
||||||
|
Size imageSize = m_imageTexture->getSize();
|
||||||
|
if(size.width() <= 0 || m_imageAutoResize)
|
||||||
|
size.setWidth(imageSize.width());
|
||||||
|
if(size.height() <= 0 || m_imageAutoResize)
|
||||||
|
size.setHeight(imageSize.height());
|
||||||
|
setSize(size);
|
||||||
|
}
|
||||||
|
|
||||||
m_imageMustRecache = true;
|
m_imageMustRecache = true;
|
||||||
}
|
}
|
||||||
|
@@ -365,7 +365,7 @@ index b980be0..7a84f61 100644
|
|||||||
+ std::string buffer = msg.getString();
|
+ std::string buffer = msg.getString();
|
||||||
+
|
+
|
||||||
+ // process additional opcodes via lua script event
|
+ // process additional opcodes via lua script event
|
||||||
+ addGameTask(&Game::parsePlayerExtendedOpcode, player->getId(), opcode, buffer);
|
+ addGameTask(&Game::parsePlayerExtendedOpcode, player->getID(), opcode, buffer);
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+void ProtocolGame::sendExtendedOpcode(uint8_t opcode, const std::string& buffer)
|
+void ProtocolGame::sendExtendedOpcode(uint8_t opcode, const std::string& buffer)
|
||||||
|
Reference in New Issue
Block a user