No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

console.lua 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. Console = {}
  2. -- private variables
  3. local SpeakTypesSettings = {
  4. say = { speakType = SpeakSay, color = '#FFFF00' },
  5. whisper = { speakType = SpeakWhisper, color = '#FFFF00' },
  6. yell = { speakType = SpeakYell, color = '#FFFF00' },
  7. broadcast = { speakType = SpeakBroadcast, color = '#F55E5E' },
  8. private = { speakType = SpeakPrivate, color = '#5FF7F7', private = true },
  9. privateRed = { speakType = SpeakPrivateRed, color = '#F55E5E', private = true },
  10. privatePlayerToPlayer = { speakType = SpeakPrivate, color = '#9F9DFD', private = true },
  11. privatePlayerToNpc = { speakType = SpeakPrivatePlayerToNpc, color = '#9F9DFD', private = true, npcChat = true },
  12. privateNpcToPlayer = { speakType = SpeakPrivateNpcToPlayer, color = '#5FF7F7', private = true, npcChat = true },
  13. channelYellow = { speakType = SpeakChannelYellow, color = '#FFFF00' },
  14. channelWhite = { speakType = SpeakChannelWhite, color = '#FFFFFF' },
  15. channelRed = { speakType = SpeakChannelRed, color = '#F55E5E' },
  16. channelOrange = { speakType = SpeakChannelOrange, color = '#FE6500' },
  17. monsterSay = { speakType = SpeakMonsterSay, color = '#FE6500', hideInConsole = true},
  18. monsterYell = { speakType = SpeakMonsterYell, color = '#FE6500', hideInConsole = true},
  19. }
  20. local SpeakTypes = {
  21. [SpeakSay] = SpeakTypesSettings.say,
  22. [SpeakWhisper] = SpeakTypesSettings.whisper,
  23. [SpeakYell] = SpeakTypesSettings.yell,
  24. [SpeakBroadcast] = SpeakTypesSettings.broadcast,
  25. [SpeakPrivate] = SpeakTypesSettings.private,
  26. [SpeakPrivateRed] = SpeakTypesSettings.privateRed,
  27. [SpeakPrivatePlayerToNpc] = SpeakTypesSettings.privatePlayerToNpc,
  28. [SpeakPrivateNpcToPlayer] = SpeakTypesSettings.privateNpcToPlayer,
  29. [SpeakChannelYellow] = SpeakTypesSettings.channelYellow,
  30. [SpeakChannelWhite] = SpeakTypesSettings.channelWhite,
  31. [SpeakChannelRed] = SpeakTypesSettings.channelRed,
  32. [SpeakChannelOrange] = SpeakTypesSettings.channelOrange,
  33. [SpeakMonsterSay] = SpeakTypesSettings.monsterSay,
  34. [SpeakMonsterYell] = SpeakTypesSettings.monsterYell,
  35. }
  36. local SayModes = {
  37. [1] = { speakTypeDesc = 'whisper', icon = '/core_styles/icons/whisper.png' },
  38. [2] = { speakTypeDesc = 'say', icon = '/core_styles/icons/say.png' },
  39. [3] = { speakTypeDesc = 'yell', icon = '/core_styles/icons/yell.png' }
  40. }
  41. local consolePanel
  42. local consoleBuffer
  43. local consoleTabBar
  44. local consoleLineEdit
  45. local channels
  46. local messageHistory = { }
  47. local currentMessageIndex = 0
  48. local MaxHistory = 1000
  49. -- private functions
  50. local function navigateMessageHistory(step)
  51. local numCommands = #messageHistory
  52. if numCommands > 0 then
  53. currentMessageIndex = math.min(math.max(currentMessageIndex + step, 0), numCommands)
  54. if currentMessageIndex > 0 then
  55. local command = messageHistory[numCommands - currentMessageIndex + 1]
  56. consoleLineEdit:setText(command)
  57. else
  58. consoleLineEdit:clearText()
  59. end
  60. end
  61. end
  62. function applyMessagePrefixies(name, level, message)
  63. if name then
  64. if Options.showLevelsInConsole and level > 0 then
  65. message = name .. ' [' .. level .. ']: ' .. message
  66. else
  67. message = name .. ': ' .. message
  68. end
  69. end
  70. return message
  71. end
  72. -- public functions
  73. function Console.create()
  74. consolePanel = displayUI('console.otui', { parent = Game.gameBottomPanel } )
  75. consoleLineEdit = consolePanel:getChildById('consoleLineEdit')
  76. consoleBuffer = consolePanel:getChildById('consoleBuffer')
  77. consoleTabBar = consolePanel:getChildById('consoleTabBar')
  78. consoleTabBar:setContentWidget(consoleBuffer)
  79. channels = {}
  80. Console.addChannel('Default', 0)
  81. Console.addTab('Server Log', false)
  82. Keyboard.bindKeyDown('Shift+Up', function() navigateMessageHistory(1) end, consolePanel)
  83. Keyboard.bindKeyDown('Shift+Down', function() navigateMessageHistory(-1) end, consolePanel)
  84. Keyboard.bindKeyDown('Tab', function() consoleTabBar:selectNextTab() end, consolePanel)
  85. Keyboard.bindKeyDown('Shift+Tab', function() consoleTabBar:selectPrevTab() end, consolePanel)
  86. Keyboard.bindKeyDown('Enter', Console.sendCurrentMessage, consolePanel)
  87. -- apply buttom functions after loaded
  88. connect(consolePanel:getChildById('nextChannelButton'), { onClick = function() consoleTabBar:selectNextTab() end } )
  89. connect(consolePanel:getChildById('prevChannelButton'), { onClick = function() consoleTabBar:selectPrevTab() end } )
  90. connect(consoleTabBar, { onTabChange = Console.onTabChange })
  91. -- tibia like hotkeys
  92. Keyboard.bindKeyDown('Ctrl+O', Game.requestChannels)
  93. Keyboard.bindKeyDown('Ctrl+E', Console.removeCurrentTab)
  94. end
  95. function Console.destroy()
  96. consolePanel:destroy()
  97. consolePanel = nil
  98. end
  99. function Console.setLineEditText(text)
  100. consoleLineEdit:setText(text)
  101. end
  102. function Console.addTab(name, focus)
  103. local tab = consoleTabBar:addTab(name)
  104. if focus then
  105. consoleTabBar:selectTab(tab)
  106. else
  107. consoleTabBar:blinkTab(tab)
  108. end
  109. return tab
  110. end
  111. function Console.onTabChange(tabBar, tab)
  112. if tab:getText() == "Default" or tab:getText() == "Server Log" then
  113. consolePanel:getChildById('closeChannelButton'):disable()
  114. else
  115. consolePanel:getChildById('closeChannelButton'):enable()
  116. end
  117. end
  118. function Console.removeCurrentTab()
  119. local tab = consoleTabBar:getCurrentTab()
  120. if tab:getText() == "Default" or tab:getText() == "Server Log" then return end
  121. consoleTabBar:removeTab(tab)
  122. -- notificate the server that we are leaving the channel
  123. if tab.channelId then
  124. Game.leaveChannel(tab.channelId)
  125. elseif tab:getText() == "NPCs" then
  126. Game.closeNpcChannel()
  127. end
  128. end
  129. function Console.getTab(name)
  130. return consoleTabBar:getTab(name)
  131. end
  132. function Console.getCurrentTab()
  133. return consoleTabBar:getCurrentTab()
  134. end
  135. function Console.addChannel(name, id)
  136. channels[id] = name
  137. local tab = Console.addTab(name, true)
  138. tab.channelId = id
  139. return tab
  140. end
  141. function Console.addPrivateText(text, speaktype, name, isPrivateCommand)
  142. local focus = false
  143. if speaktype.speakType == SpeakPrivateNpcToPlayer then
  144. name = 'NPCs'
  145. focus = true
  146. end
  147. local privateTab = Console.getTab(name)
  148. if privateTab == nil then
  149. if Options.showPrivateMessagesInConsole or (isPrivateCommand and not privateTab) then
  150. privateTab = Console.getTab('Default')
  151. else
  152. privateTab = Console.addTab(name, focus)
  153. end
  154. privateTab.npcChat = speaktype.npcChat
  155. elseif focus then
  156. consoleTabBar:selectTab(privateTab)
  157. end
  158. Console.addTabText(text, speaktype, privateTab)
  159. end
  160. function Console.addText(text, speaktype, tabName)
  161. local tab = Console.getTab(tabName)
  162. if tab ~= nil then
  163. Console.addTabText(text, speaktype, tab)
  164. end
  165. end
  166. function Console.addTabText(text, speaktype, tab)
  167. if Options.showTimestampsInConsole then
  168. text = os.date('%H:%M') .. ' ' .. text
  169. end
  170. local panel = consoleTabBar:getTabPanel(tab)
  171. local label = createWidget('ConsoleLabel', panel)
  172. label:setText(text)
  173. label:setColor(speaktype.color)
  174. consoleTabBar:blinkTab(tab)
  175. if panel:getChildCount() > 10 then
  176. panel:removeChild(panel:getFirstChild())
  177. end
  178. end
  179. function Console.sendCurrentMessage()
  180. local message = consoleLineEdit:getText()
  181. if #message == 0 then return end
  182. consoleLineEdit:clearText()
  183. -- get current channel
  184. local tab = Console.getCurrentTab()
  185. -- handling chat commands
  186. local originalMessage = message
  187. local chatCommandSayMode
  188. local chatCommandPrivate
  189. local chatCommandPrivateReady
  190. local chatCommandMessage = message:match("^%#y (.*)")
  191. if chatCommandMessage ~= nil then chatCommandSayMode = 'yell' end -- player used yell command
  192. message = chatCommandMessage or message
  193. local chatCommandMessage = message:match("^%#w (.*)")
  194. if chatCommandMessage ~= nil then chatCommandSayMode = 'whisper' end -- player used whisper
  195. message = chatCommandMessage or message
  196. local findIni, findEnd, chatCommandInitial, chatCommandPrivate, chatCommandEnd, chatCommandMessage = message:find("([%*%@])(.+)([%*%@])(.*)")
  197. if findIni ~= nil and findIni == 1 then -- player used private chat command
  198. if chatCommandInitial == chatCommandEnd then
  199. chatCommandPrivateRepeat = false
  200. if chatCommandInitial == "*" then
  201. consoleLineEdit:setText('*'.. chatCommandPrivate .. '* ')
  202. end
  203. message = chatCommandMessage:trim()
  204. chatCommandPrivateReady = true
  205. end
  206. end
  207. message = message:gsub("^(%s*)(.*)","%2") -- remove space characters from message init
  208. if #message == 0 then return end
  209. -- add new command to history
  210. currentMessageIndex = 0
  211. table.insert(messageHistory, originalMessage)
  212. if #messageHistory > MaxHistory then
  213. table.remove(messageHistory, 1)
  214. end
  215. -- when talking on server log, the message goes to default channel
  216. local name = tab:getText()
  217. if name == 'Server Log' then
  218. tab = Console.getTab('Default')
  219. name = 'Default'
  220. end
  221. local speaktypedesc
  222. if tab.channelId and not chatCommandPrivateReady then
  223. if tab.channelId == 0 then
  224. speaktypedesc = chatCommandSayMode or SayModes[consolePanel:getChildById('sayModeButton').sayMode].speakTypeDesc
  225. if speaktypedesc ~= 'say' then Console.sayModeChange(2) end -- head back to say mode
  226. else
  227. speaktypedesc = 'channelYellow'
  228. end
  229. Game.talkChannel(SpeakTypesSettings[speaktypedesc].speakType, tab.channelId, message)
  230. return
  231. else
  232. local isPrivateCommand = false
  233. if chatCommandPrivateReady then
  234. speaktypedesc = 'privatePlayerToPlayer'
  235. name = chatCommandPrivate
  236. isPrivateCommand = true
  237. elseif tab.npcChat then
  238. speaktypedesc = 'privatePlayerToNpc'
  239. else
  240. speaktypedesc = 'privatePlayerToPlayer'
  241. end
  242. local speaktype = SpeakTypesSettings[speaktypedesc]
  243. local player = Game.getLocalPlayer()
  244. Game.talkPrivate(speaktype.speakType, name, message)
  245. message = applyMessagePrefixies(player:getName(), player:getLevel(), message)
  246. Console.addPrivateText(message, speaktype, name, isPrivateCommand)
  247. end
  248. end
  249. function Console.sayModeChange(sayMode)
  250. local buttom = consolePanel:getChildById('sayModeButton')
  251. if sayMode == nil then
  252. sayMode = buttom.sayMode + 1
  253. end
  254. if sayMode > #SayModes then sayMode = 1 end
  255. buttom:setIcon(SayModes[sayMode].icon)
  256. buttom.sayMode = sayMode
  257. end
  258. -- hooked events
  259. local function onCreatureSpeak(name, level, speaktype, message, channelId, creaturePos)
  260. speaktype = SpeakTypes[speaktype]
  261. if speaktype.hideInConsole then return end
  262. message = applyMessagePrefixies(name, level, message)
  263. if speaktype.private then
  264. Console.addPrivateText(message, speaktype, name, false)
  265. else
  266. local channel = channels[channelId]
  267. if channel then
  268. Console.addText(message, speaktype, channel)
  269. else
  270. -- server sent a message on a channel that we are not aware of, must leave it
  271. Game.leaveChannel(channelId)
  272. end
  273. end
  274. end
  275. local function onOpenChannel(channelId, channelName)
  276. Console.addChannel(channelName, channelId)
  277. end
  278. local function onOpenPrivateChannel(receiver)
  279. local privateTab = Console.getTab(receiver)
  280. if privateTab == nil then
  281. Console.addTab(receiver, true)
  282. end
  283. end
  284. local function doChannelListSubmit(channelsWindow)
  285. local channelListPanel = channelsWindow:getChildById('channelList')
  286. local openPrivateChannelWith = channelsWindow:getChildById('openPrivateChannelWith'):getText()
  287. if openPrivateChannelWith ~= '' then
  288. Game.openPrivateChannel(openPrivateChannelWith)
  289. else
  290. local selectedChannelLabel = channelListPanel:getFocusedChild()
  291. if not selectedChannelLabel then return end
  292. Game.joinChannel(selectedChannelLabel.channelId)
  293. end
  294. channelsWindow:destroy()
  295. end
  296. local function onChannelList(channelList)
  297. local channelsWindow = displayUI('channelswindow.otui')
  298. local channelListPanel = channelsWindow:getChildById('channelList')
  299. connect(channelsWindow, { onEnter = function () doChannelListSubmit(channelsWindow) end } )
  300. for k,v in pairs(channelList) do
  301. local channelId = v[1]
  302. local channelName = v[2]
  303. if channelId ~= 0 and #channelName > 0 then
  304. local label = createWidget('ChannelListLabel', channelListPanel)
  305. label.channelId = channelId
  306. label:setText(channelName)
  307. label:setPhantom(false)
  308. connect(label, { onDoubleClick = function () doChannelListSubmit(channelsWindow) end } )
  309. end
  310. end
  311. end
  312. connect(Game, { onGameStart = Console.create,
  313. onGameEnd = Console.destroy,
  314. onCreatureSpeak = onCreatureSpeak,
  315. onChannelList = onChannelList,
  316. onOpenChannel = onOpenChannel,
  317. onOpenPrivateChannel = onOpenPrivateChannel})