add chat panel, send text messages, guard forbidden functions with an ifdef

This commit is contained in:
Eduardo Bart 2011-11-03 18:54:53 -02:00
parent 6d6479e4a9
commit b216b00a32
16 changed files with 142 additions and 37 deletions

View File

@ -7,6 +7,7 @@ SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}")
OPTION(USE_PCH "Use precompiled header" ON) OPTION(USE_PCH "Use precompiled header" ON)
OPTION(NO_CONSOLE "Disable console window on Windows" OFF) OPTION(NO_CONSOLE "Disable console window on Windows" OFF)
OPTION(HANDLE_EXCEPTIONS "Generate crash reports" OFF) OPTION(HANDLE_EXCEPTIONS "Generate crash reports" OFF)
OPTION(FORBIDDEN_FUNCTIONS "Enable forbidden lua functions" ON)
# find needed packages # find needed packages
SET(Boost_USE_STATIC_LIBS ON) SET(Boost_USE_STATIC_LIBS ON)
@ -141,6 +142,10 @@ IF(HANDLE_EXCEPTIONS)
ADD_DEFINITIONS(-DHANDLE_EXCEPTIONS) ADD_DEFINITIONS(-DHANDLE_EXCEPTIONS)
ENDIF(HANDLE_EXCEPTIONS) ENDIF(HANDLE_EXCEPTIONS)
IF(FORBIDDEN_FUNCTIONS)
ADD_DEFINITIONS(-DFORBIDDEN_FUNCTIONS)
ENDIF(FORBIDDEN_FUNCTIONS)
IF(WIN32) IF(WIN32)
SET(SOURCES ${SOURCES} src/framework/platform/win32platform.cpp) SET(SOURCES ${SOURCES} src/framework/platform/win32platform.cpp)
SET(ADDITIONAL_LIBRARIES ws2_32) SET(ADDITIONAL_LIBRARIES ws2_32)

19
modules/chat/chat.lua Normal file
View File

@ -0,0 +1,19 @@
Chat = {}
-- private variables
local chatPanel
-- public functions
function Chat.create()
chatPanel = loadUI("/chat/chat.otui", Game.gameBottomPanel)
end
function Chat.destroy()
chatPanel:destroy()
chatPanel = nil
end
-- hooked events
connect(Game, { onLogin = Chat.create,
onLogout = Chat.destroy })

14
modules/chat/chat.otmod Normal file
View File

@ -0,0 +1,14 @@
Module
name: chat
description: Manage chat window
author: OTClient team
website: https://github.com/edubart/otclient
autoLoad: true
dependencies:
- game
onLoad: |
require 'chat'
return true

30
modules/chat/chat.otui Normal file
View File

@ -0,0 +1,30 @@
ChatLabel < UILabel
font: verdana-11px-monochrome
height: 16
Panel
id: chatPanel
anchors.fill: parent
Panel
id: chatBuffer
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: next.top
margin.right: 6
margin.left: 6
margin.bottom: 2
margin.top: 6
layout: verticalBox
focusable: false
LineEdit
id: chatLineEdit
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
margin.right: 6
margin.left: 6
margin.bottom: 6
always focused: true

View File

@ -8,7 +8,7 @@ RectPanel
opacity: 216 opacity: 216
anchors.fill: parent anchors.fill: parent
UIWidget Panel
id: consoleBuffer id: consoleBuffer
layout: verticalBox layout: verticalBox
focusable: false focusable: false

View File

@ -18,9 +18,8 @@ function connect(object, signalsAndSlots)
object[signal] = slot object[signal] = slot
elseif type(object[signal]) == 'function' then elseif type(object[signal]) == 'function' then
object[signal] = { object[signal], slot } object[signal] = { object[signal], slot }
elseif type(signal) == 'table' then elseif type(object[signal]) == 'table' then
table.insert(object[signal], slot) table.insert(object[signal], #object[signal]+1, slot)
else
end end
end end
end end

View File

@ -15,20 +15,23 @@ local function onGameKeyPress(self, keyCode, keyChar, keyboardModifiers)
end end
-- public functions -- public functions
function Game.create() function Game.createInterface()
Background.hide()
CharacterList.destroyLoadBox()
Game.gameUi = loadUI('/game/ui/gameinterface.otui', UI.root) Game.gameUi = loadUI('/game/ui/gameinterface.otui', UI.root)
Game.gameMapPanel = Game.gameUi:getChildById('mapPanel') Game.gameMapPanel = Game.gameUi:getChildById('mapPanel')
Game.gameRightPanel = Game.gameUi:getChildById('rightPanel') Game.gameRightPanel = Game.gameUi:getChildById('rightPanel')
Game.gameBottomPanel = Game.gameUi:getChildById('bottomPanel')
Game.gameUi.onKeyPress = onGameKeyPress Game.gameUi.onKeyPress = onGameKeyPress
TextMessage.create()
end end
function Game.destroy() function Game.destroyInterface()
if Game.gameUi then if Game.gameUi then
Game.gameUi:destroy() Game.gameUi:destroy()
Game.gameUi = nil Game.gameUi = nil
end end
Background.show()
CharacterList.show()
end end
function Game.show() function Game.show()
@ -42,12 +45,6 @@ function Game.hide()
end end
-- hooked events -- hooked events
function Game.onLogin()
Background.hide()
CharacterList.destroyLoadBox()
Game.show()
end
function Game.onLoginError(message) function Game.onLoginError(message)
CharacterList.destroyLoadBox() CharacterList.destroyLoadBox()
local errorBox = displayErrorBox("Login Error", "Login error: " .. message) local errorBox = displayErrorBox("Login Error", "Login error: " .. message)
@ -60,8 +57,5 @@ function Game.onConnectionError(message)
errorBox.onOk = CharacterList.show errorBox.onOk = CharacterList.show
end end
function Game.onLogout() connect(Game, { onLogin = Game.createInterface,
Game.hide() onLogout = Game.destroyInterface })
Background.show()
CharacterList.show()
end

View File

@ -13,7 +13,4 @@ Module
onLoad: | onLoad: |
require 'game' require 'game'
require 'textmessage'
Game.create()
Game.hide()
return true return true

View File

@ -44,3 +44,6 @@ function Game.setSkill(id, level, percent)
local skillPanel = skillWindow:getChildById('skillPanel') local skillPanel = skillWindow:getChildById('skillPanel')
local levelLabel = skillPanel:getChildById('skillLevel' .. id) local levelLabel = skillPanel:getChildById('skillLevel' .. id)
end end
connect(Game, { onLogin = Skills.create,
onLogout = Skills.destroy })

View File

@ -9,10 +9,6 @@ Module
onLoad: | onLoad: |
require 'skills' require 'skills'
Skills.create()
return true return true
onUnload:
Skills.destroy()

View File

@ -44,3 +44,6 @@ function Game.onVipStateChange(id, online)
label.vipOnline = online label.vipOnline = online
end end
connect(Game, { onLogin = VipList.create,
onLogout = VipList.destroy })

View File

@ -9,10 +9,6 @@ Module
onLoad: | onLoad: |
require 'viplist' require 'viplist'
VipList.create()
return true return true
onUnload:
VipList.destroy()

View File

@ -33,6 +33,7 @@ UILineEdit::UILineEdit()
m_startRenderPos = 0; m_startRenderPos = 0;
m_textHorizontalMargin = 0; m_textHorizontalMargin = 0;
m_textHidden = false; m_textHidden = false;
m_alwaysFocused = false;
blinkCursor(); blinkCursor();
} }
@ -50,7 +51,7 @@ void UILineEdit::render()
g_graphics.drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]); g_graphics.drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]);
// render cursor // render cursor
if(isExplicitlyEnabled() && isActive() && m_cursorPos >= 0) { if(isExplicitlyEnabled() && (isActive() || m_alwaysFocused) && m_cursorPos >= 0) {
assert(m_cursorPos <= textLength); assert(m_cursorPos <= textLength);
// draw every 333ms // draw every 333ms
const int delay = 333; const int delay = 333;
@ -384,6 +385,8 @@ void UILineEdit::onStyleApply(const OTMLNodePtr& styleNode)
setTextHidden(node->value<bool>()); setTextHidden(node->value<bool>());
} else if(node->tag() == "text margin") { } else if(node->tag() == "text margin") {
m_textHorizontalMargin = node->value<int>(); m_textHorizontalMargin = node->value<int>();
} else if(node->tag() == "always focused") {
m_alwaysFocused = true;
} }
} }
} }
@ -395,7 +398,7 @@ void UILineEdit::onGeometryUpdate(const Rect& oldRect, const Rect& newRect)
void UILineEdit::onFocusChange(bool focused, Fw::FocusReason reason) void UILineEdit::onFocusChange(bool focused, Fw::FocusReason reason)
{ {
if(focused) { if(focused && !m_alwaysFocused) {
if(reason == Fw::TabFocusReason) if(reason == Fw::TabFocusReason)
setCursorPos(m_text.length()); setCursorPos(m_text.length());
else else
@ -420,8 +423,10 @@ bool UILineEdit::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
else if(keyCode == Fw::KeyV && keyboardModifiers == Fw::KeyboardCtrlModifier) else if(keyCode == Fw::KeyV && keyboardModifiers == Fw::KeyboardCtrlModifier)
appendText(g_platform.getClipboardText()); appendText(g_platform.getClipboardText());
else if(keyCode == Fw::KeyTab) { else if(keyCode == Fw::KeyTab) {
if(UIWidgetPtr parent = getParent()) if(!m_alwaysFocused) {
parent->focusNextChild(Fw::TabFocusReason); if(UIWidgetPtr parent = getParent())
parent->focusNextChild(Fw::TabFocusReason);
}
} else if(keyChar != 0) } else if(keyChar != 0)
appendCharacter(keyChar); appendCharacter(keyChar);
else else

View File

@ -71,6 +71,7 @@ private:
int m_cursorTicks; int m_cursorTicks;
int m_textHorizontalMargin; int m_textHorizontalMargin;
bool m_textHidden; bool m_textHidden;
bool m_alwaysFocused;
std::vector<Rect> m_glyphsCoords; std::vector<Rect> m_glyphsCoords;
std::vector<Rect> m_glyphsTexCoords; std::vector<Rect> m_glyphsTexCoords;

View File

@ -63,9 +63,13 @@ void OTClient::registerLuaFunctions()
g_lua.bindClassStaticFunction<Game>("logout", std::bind(&Game::logout, &g_game, _1)); g_lua.bindClassStaticFunction<Game>("logout", std::bind(&Game::logout, &g_game, _1));
g_lua.bindClassStaticFunction<Game>("cancelLogin", std::bind(&Game::cancelLogin, &g_game)); g_lua.bindClassStaticFunction<Game>("cancelLogin", std::bind(&Game::cancelLogin, &g_game));
g_lua.bindClassStaticFunction<Game>("isOnline", std::bind(&Game::isOnline, &g_game)); g_lua.bindClassStaticFunction<Game>("isOnline", std::bind(&Game::isOnline, &g_game));
g_lua.bindClassStaticFunction<Game>("talkChannel", std::bind(&Game::talkChannel, &g_game, _1, _2, _3)); g_lua.bindClassStaticFunction<Game>("isOnline", std::bind(&Game::isOnline, &g_game));
g_lua.bindClassStaticFunction<Game>("talkPrivate", std::bind(&Game::talkPrivate, &g_game, _1, _2, _3));
g_lua.registerClass<UIMap, UIWidget>(); g_lua.registerClass<UIMap, UIWidget>();
g_lua.bindClassStaticFunction<UIMap>("create", &UIWidget::create<UIMap>); g_lua.bindClassStaticFunction<UIMap>("create", &UIWidget::create<UIMap>);
#ifdef FORBIDDEN_FUNCTIONS
g_lua.bindClassStaticFunction<Game>("talkChannel", std::bind(&Game::talkChannel, &g_game, _1, _2, _3));
g_lua.bindClassStaticFunction<Game>("talkPrivate", std::bind(&Game::talkPrivate, &g_game, _1, _2, _3));
#endif
} }

View File

@ -25,6 +25,7 @@
#include <otclient/core/game.h> #include <otclient/core/game.h>
#include <framework/otml/otml.h> #include <framework/otml/otml.h>
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include <framework/ui/uilineedit.h>
void UIMap::setup() void UIMap::setup()
{ {
@ -46,6 +47,8 @@ void UIMap::render()
bool UIMap::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers) bool UIMap::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
{ {
UILineEditPtr chatLineEdit = std::dynamic_pointer_cast<UILineEdit>(getParent()->recursiveGetChildById("chatLineEdit"));
if(keyboardModifiers == Fw::KeyboardNoModifier) { if(keyboardModifiers == Fw::KeyboardNoModifier) {
if(keyCode == Fw::KeyUp || keyCode == Fw::KeyNumpad8) { if(keyCode == Fw::KeyUp || keyCode == Fw::KeyNumpad8) {
g_game.walk(Otc::North); g_game.walk(Otc::North);
@ -71,6 +74,28 @@ bool UIMap::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
} else if(keyCode == Fw::KeyNumpad7) { } else if(keyCode == Fw::KeyNumpad7) {
g_game.walk(Otc::NorthWest); g_game.walk(Otc::NorthWest);
return true; return true;
} else if(keyCode == Fw::KeyReturn || keyCode == Fw::KeyEnter) {
g_game.talkChannel(1, 0, chatLineEdit->getText());
chatLineEdit->clearText();
return true;
} else if(keyCode == Fw::KeyDelete) {
chatLineEdit->removeCharacter(true);
return true;
} else if(keyCode == Fw::KeyBackspace) {
chatLineEdit->removeCharacter(false);
return true;
} else if(keyCode == Fw::KeyRight) {
chatLineEdit->moveCursor(true);
return true;
} else if(keyCode == Fw::KeyLeft) {
chatLineEdit->moveCursor(false);
return true;
} else if(keyCode == Fw::KeyHome) {
chatLineEdit->setCursorPos(0);
return true;
} else if(keyCode == Fw::KeyEnd) {
chatLineEdit->setCursorPos(chatLineEdit->getText().length());
return true;
} }
} else if(keyboardModifiers == Fw::KeyboardCtrlModifier) { } else if(keyboardModifiers == Fw::KeyboardCtrlModifier) {
if(keyCode == Fw::KeyUp || keyCode == Fw::KeyNumpad8) { if(keyCode == Fw::KeyUp || keyCode == Fw::KeyNumpad8) {
@ -86,7 +111,21 @@ bool UIMap::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
g_game.turn(Otc::West); g_game.turn(Otc::West);
return true; return true;
} }
} else if(keyboardModifiers == Fw::KeyboardShiftModifier) {
if(keyCode == Fw::KeyRight || keyCode == Fw::KeyNumpad6) {
chatLineEdit->moveCursor(true);
return true;
} else if(keyCode == Fw::KeyLeft || keyCode == Fw::KeyNumpad4) {
chatLineEdit->moveCursor(false);
return true;
}
} }
if(keyChar != 0) {
chatLineEdit->appendText(std::string(1, keyChar));
return true;
}
return UIWidget::onKeyPress(keyCode, keyChar, keyboardModifiers); return UIWidget::onKeyPress(keyCode, keyChar, keyboardModifiers);
} }