summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml17
-rw-r--r--src/being/being.cpp19
-rw-r--r--src/defaults.cpp14
-rw-r--r--src/game.cpp2
-rw-r--r--src/gui/sdlinput.cpp16
-rw-r--r--src/gui/widgets/tabs/chat/battletab.cpp2
-rw-r--r--src/gui/widgets/tabs/chat/chattab.cpp9
-rw-r--r--src/gui/widgets/tabs/chat/chattab.h3
-rw-r--r--src/gui/widgets/tabs/setup_chat.cpp9
-rw-r--r--src/gui/widgets/tabs/setup_joystick.cpp82
-rw-r--r--src/gui/widgets/tabs/setup_joystick.h6
-rw-r--r--src/gui/windows/chatwindow.cpp4
-rw-r--r--src/gui/windows/ministatuswindow.cpp7
-rw-r--r--src/gui/windows/quitdialog.cpp5
-rw-r--r--src/gui/windows/registerdialog.cpp15
-rw-r--r--src/gui/windows/registerdialog.h2
-rw-r--r--src/gui/windows/updaterwindow.cpp3
-rw-r--r--src/input/inputmanager.cpp125
-rw-r--r--src/input/joystick.cpp291
-rw-r--r--src/input/joystick.h67
-rw-r--r--src/net/ea/partyrecv.cpp2
-rw-r--r--src/net/eathena/clanrecv.cpp2
-rw-r--r--src/net/eathena/guildrecv.cpp2
-rw-r--r--src/net/eathena/inventoryhandler.cpp2
-rw-r--r--src/net/eathena/packetsin.inc4
-rw-r--r--src/net/tmwa/guildmanager.cpp2
-rw-r--r--src/net/tmwa/inventoryhandler.cpp3
-rw-r--r--src/net/tmwa/loginrecv.cpp23
-rwxr-xr-xtools/ci/jobs/mplint.sh25
-rwxr-xr-xtools/ci/scripts/exit.sh2
-rwxr-xr-xtools/ci/scripts/init.sh39
31 files changed, 500 insertions, 304 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 116bceed0..6b59b54db 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -327,30 +327,23 @@ gcc-8_unittestsbin:
tags:
- docker
-mplint:
- stage: lint
- script:
- - ./tools/ci/jobs/mplint.sh src po data
- <<: *job-push
- variables:
- PACKAGES: gcc g++ git
- make autoconf automake autopoint gettext
- tags:
- - docker
linters:
stage: lint
image: debian:buster
script:
+ - ./tools/ci/jobs/mplint.sh src po data
- ./tools/ci/jobs/pngcheck.sh
- ./tools/ci/jobs/imagemagiccheck.sh
- ./tools/ci/jobs/cpplint.sh
- ./tools/ci/jobs/nsiqcppstyle.sh
<<: *job-push
variables:
- PACKAGES: python wget pngcheck imagemagick git grep
+ MPLINT_PACKAGE_URL: "$CI_API_V4_URL/projects/mana%2Fmplint/jobs/artifacts/master/download?job=package_debian10_buster"
+ PACKAGES: git grep imagemagick pngcheck python unzip wget
tags:
- - lightweight
+ - docker
+
gcc-5_h_all:
stage: prebuild
diff --git a/src/being/being.cpp b/src/being/being.cpp
index e918877a1..6dd797eac 100644
--- a/src/being/being.cpp
+++ b/src/being/being.cpp
@@ -4309,8 +4309,8 @@ void Being::drawHpBar(Graphics *restrict const graphics,
const int maxHP,
const int hp,
const int damage,
- const UserColorIdT color1,
- const UserColorIdT color2,
+ const UserColorIdT colorFG,
+ const UserColorIdT colorBG,
const int x,
const int y,
const int width,
@@ -4346,13 +4346,13 @@ void Being::drawHpBar(Graphics *restrict const graphics,
if ((damage == 0 && (this != localPlayer || hp == maxHP))
|| (hp == 0 && maxHP == damage))
{
- graphics->setColor(userPalette->getColorWithAlpha(color1));
+ graphics->setColor(userPalette->getColorWithAlpha(colorFG));
graphics->fillRectangle(Rect(x, y, dx, height));
return;
}
else if (width - dx <= 0)
{
- graphics->setColor(userPalette->getColorWithAlpha(color2));
+ graphics->setColor(userPalette->getColorWithAlpha(colorBG));
graphics->fillRectangle(Rect(x, y, width, height));
return;
}
@@ -4362,22 +4362,23 @@ void Being::drawHpBar(Graphics *restrict const graphics,
{
if (hp == maxHP)
{
- graphics->setColor(userPalette->getColorWithAlpha(color1));
+ graphics->setColor(userPalette->getColorWithAlpha(colorFG));
graphics->fillRectangle(Rect(x, y, dx, height));
return;
}
else if (width - dx <= 0)
{
- graphics->setColor(userPalette->getColorWithAlpha(color2));
+ graphics->setColor(userPalette->getColorWithAlpha(colorBG));
graphics->fillRectangle(Rect(x, y, width, height));
return;
}
}
- graphics->setColor(userPalette->getColorWithAlpha(color1));
+ // foreground
+ graphics->setColor(userPalette->getColorWithAlpha(colorFG));
graphics->fillRectangle(Rect(x, y, dx, height));
-
- graphics->setColor(userPalette->getColorWithAlpha(color2));
+ // background
+ graphics->setColor(userPalette->getColorWithAlpha(colorBG));
graphics->fillRectangle(Rect(x + dx, y, width - dx, height));
}
diff --git a/src/defaults.cpp b/src/defaults.cpp
index 4869de8ef..eae83e1ab 100644
--- a/src/defaults.cpp
+++ b/src/defaults.cpp
@@ -189,15 +189,9 @@ void setConfigDefaults(Configuration &cfg)
AddDEF("screenshotDirectory3", "");
AddDEF("useScreenshotDirectorySuffix", true);
AddDEF("screenshotDirectorySuffix", "");
-#ifdef __SWITCH__
AddDEF("joystickEnabled", true);
-#else
- AddDEF("joystickEnabled", false);
-#endif
- AddDEF("upTolerance", 100);
- AddDEF("downTolerance", 100);
- AddDEF("leftTolerance", 100);
- AddDEF("rightTolerance", 100);
+ AddDEF("joystickTolerance", 0.3F);
+ AddDEF("useHatForMovement", true);
AddDEF("logNpcInGui", true);
AddDEF("download-music", true);
AddDEF("guialpha", 0.8F);
@@ -238,8 +232,8 @@ void setConfigDefaults(Configuration &cfg)
AddDEF("allowCommandsInChatTabs", true);
AddDEF("serverMsgInDebug", true);
AddDEF("hideShopMessages", true);
- AddDEF("showChatHistory", true);
- AddDEF("chatMaxLinesLimit", 40);
+ AddDEF("loadChatHistoryLines", 100);
+ AddDEF("chatMaxLinesLimit", 100);
AddDEF("chatColor", 0);
AddDEF("showJob", true);
AddDEF("updateOnlineList", true);
diff --git a/src/game.cpp b/src/game.cpp
index 4e3c399cd..69daa254d 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -293,8 +293,6 @@ static void createGuiWindows()
localChatTab = new ChatTab(chatWindow, _("General"),
GENERAL_CHANNEL, "#General", ChatTabType::INPUT);
localChatTab->setAllowHighlight(false);
- if (config.getBoolValue("showChatHistory"))
- localChatTab->loadFromLogFile("#General");
// TRANSLATORS: chat tab header
debugChatTab = new ChatTab(chatWindow, _("Debug"), "",
diff --git a/src/gui/sdlinput.cpp b/src/gui/sdlinput.cpp
index 9b8b1ec6a..8f3ca8bff 100644
--- a/src/gui/sdlinput.cpp
+++ b/src/gui/sdlinput.cpp
@@ -171,6 +171,22 @@ void SDLInput::pushInput(const SDL_Event &event)
break;
}
+ case SDL_JOYBUTTONDOWN:
+ case SDL_JOYHATMOTION:
+ case SDL_JOYAXISMOTION:
+ {
+ const InputActionT actionId = inputManager.getActionByKey(event);
+ if (actionId > InputAction::NO_VALUE)
+ {
+ keyInput.setActionId(actionId);
+ keyInput.setType(KeyEventType::PRESSED);
+ mKeyInputQueue.push(keyInput);
+ keyInput.setType(KeyEventType::RELEASED);
+ mKeyInputQueue.push(keyInput);
+ }
+ break;
+ }
+
#ifdef USE_SDL2
case SDL_TEXTINPUT:
keyInput.setType(KeyEventType::PRESSED);
diff --git a/src/gui/widgets/tabs/chat/battletab.cpp b/src/gui/widgets/tabs/chat/battletab.cpp
index 5dd5ff987..9fa18e945 100644
--- a/src/gui/widgets/tabs/chat/battletab.cpp
+++ b/src/gui/widgets/tabs/chat/battletab.cpp
@@ -36,8 +36,6 @@ BattleTab::BattleTab(const Widget2 *const widget) :
ChatTab(widget, _("Battle"), "", "#Battle", ChatTabType::BATTLE)
{
setTabColors(ThemeColorId::BATTLE_CHAT_TAB);
- if (config.getBoolValue("showChatHistory"))
- loadFromLogFile("#Battle");
}
BattleTab::~BattleTab()
diff --git a/src/gui/widgets/tabs/chat/chattab.cpp b/src/gui/widgets/tabs/chat/chattab.cpp
index ec9042694..3773df55f 100644
--- a/src/gui/widgets/tabs/chat/chattab.cpp
+++ b/src/gui/widgets/tabs/chat/chattab.cpp
@@ -97,6 +97,10 @@ ChatTab::ChatTab(const Widget2 *const widget,
if (chatWindow != nullptr)
chatWindow->addTab(this);
mTextOutput->updateSize(true);
+
+ const int maxLines = config.getIntValue("loadChatHistoryLines");
+ if (maxLines > 0)
+ loadFromLogFile(logName, maxLines);
}
ChatTab::~ChatTab()
@@ -510,12 +514,13 @@ void ChatTab::addRow(std::string &line)
false);
}
-void ChatTab::loadFromLogFile(const std::string &name)
+void ChatTab::loadFromLogFile(const std::string &name,
+ const unsigned maxLines)
{
if (chatLogger != nullptr)
{
std::list<std::string> list;
- chatLogger->loadLast(name, list, 5);
+ chatLogger->loadLast(name, list, maxLines);
std::list<std::string>::const_iterator i = list.begin();
while (i != list.end())
{
diff --git a/src/gui/widgets/tabs/chat/chattab.h b/src/gui/widgets/tabs/chat/chattab.h
index 7a3774fc2..7aeeeebdb 100644
--- a/src/gui/widgets/tabs/chat/chattab.h
+++ b/src/gui/widgets/tabs/chat/chattab.h
@@ -153,7 +153,8 @@ class ChatTab notfinal : public Tab
bool hasRows() const A_WARN_UNUSED
{ return mTextOutput->hasRows(); }
- void loadFromLogFile(const std::string &name);
+ void loadFromLogFile(const std::string &name,
+ const unsigned maxLines);
bool getAllowHighlight() const noexcept2 A_WARN_UNUSED
{ return mAllowHightlight; }
diff --git a/src/gui/widgets/tabs/setup_chat.cpp b/src/gui/widgets/tabs/setup_chat.cpp
index f42f34c5a..ae9043962 100644
--- a/src/gui/widgets/tabs/setup_chat.cpp
+++ b/src/gui/widgets/tabs/setup_chat.cpp
@@ -148,11 +148,12 @@ Setup_Chat::Setup_Chat(const Widget2 *const widget) :
MainConfig_true);
// TRANSLATORS: settings option
- new SetupItemCheckBox(_("Show chat history"),
+ new SetupItemIntTextField(_("Show chat history lines"),
// TRANSLATORS: settings description
- _("If this setting enabled, client will load old chat tabs content "
- "from logs on startup instead of starting with empty chat tabs."),
- "showChatHistory", this, "showChatHistoryEvent",
+ _("If this number is set to above 0, the client will load old chat"
+ " tabs content from logs on startup instead of starting with empty"
+ " chat tabs."),
+ "loadChatHistoryLines", this, "loadChatHistoryLinesEvent", 0, 10000,
MainConfig_true);
// TRANSLATORS: settings option
diff --git a/src/gui/widgets/tabs/setup_joystick.cpp b/src/gui/widgets/tabs/setup_joystick.cpp
index ab623b901..297f5bafc 100644
--- a/src/gui/widgets/tabs/setup_joystick.cpp
+++ b/src/gui/widgets/tabs/setup_joystick.cpp
@@ -35,6 +35,7 @@
#include "gui/widgets/dropdown.h"
#include "gui/widgets/label.h"
#include "gui/widgets/layouthelper.h"
+#include "gui/widgets/slider.h"
#include "utils/delete2.h"
#include "utils/gettext.h"
@@ -43,12 +44,6 @@
Setup_Joystick::Setup_Joystick(const Widget2 *const widget) :
SetupTab(widget),
- mCalibrateLabel(new Label(this,
- // TRANSLATORS: joystick settings tab label
- _("Press the button to start calibration"))),
- // TRANSLATORS: joystick settings tab button
- mCalibrateButton(new Button(this, _("Calibrate"), "calibrate",
- BUTTON_SKIN, this)),
// TRANSLATORS: joystick settings tab button
mDetectButton(new Button(this, _("Detect joysticks"), "detect",
BUTTON_SKIN, this)),
@@ -58,6 +53,13 @@ Setup_Joystick::Setup_Joystick(const Widget2 *const widget) :
mNamesModel(new NamesModel),
mNamesDropDown(new DropDown(this, mNamesModel,
false, Modal_false, nullptr, std::string())),
+ mToleranceLabel(new Label(this)),
+ mToleranceSlider(new Slider(this, 0.01, 1, 0.01)),
+ mUseHatForMovementCheckBox(new CheckBox(this,
+ // TRANSLATORS: joystick settings tab checkbox
+ _("Use joystick hat (d-pad) for movement"),
+ config.getBoolValue("useHatForMovement"),
+ nullptr, std::string())),
mUseInactiveCheckBox(new CheckBox(this,
// TRANSLATORS: joystick settings tab checkbox
_("Use joystick if client window inactive"),
@@ -73,10 +75,19 @@ Setup_Joystick::Setup_Joystick(const Widget2 *const widget) :
mJoystickEnabled->setSelected(mOriginalJoystickEnabled);
mJoystickEnabled->setActionEventId("joystick");
mJoystickEnabled->addActionListener(this);
- mCalibrateButton->setEnabled(mOriginalJoystickEnabled);
+
+ const float tolerance = config.getFloatValue("joystickTolerance");
+ mToleranceSlider->setValue(tolerance);
+ // TRANSLATORS: joystick settings tab label
+ mToleranceLabel->setCaption(_("joystick dead zone: ")
+ + strprintf("%.2f", tolerance));
+ mToleranceLabel->setWidth(150);
+ mToleranceLabel->setHeight(20);
mNamesDropDown->setActionEventId("name");
mNamesDropDown->addActionListener(this);
+ mToleranceSlider->setActionEventId("toleranceslider");
+ mToleranceSlider->addActionListener(this);
if (joystick != nullptr)
{
@@ -96,10 +107,13 @@ Setup_Joystick::Setup_Joystick(const Widget2 *const widget) :
place(0, 0, mJoystickEnabled, 1, 1);
place(0, 1, mNamesDropDown, 1, 1);
- place(0, 2, mUseInactiveCheckBox, 1, 1);
- place(0, 3, mDetectButton, 1, 1);
- place(0, 4, mCalibrateLabel, 1, 1);
- place(0, 5, mCalibrateButton, 1, 1);
+
+ place(0, 2, mToleranceSlider, 1, 1);
+ place(1, 2, mToleranceLabel, 1, 1).setPadding(3);
+
+ place(0, 3, mUseHatForMovementCheckBox, 1, 1);
+ place(0, 4, mUseInactiveCheckBox, 1, 1);
+ place(0, 5, mDetectButton, 1, 1);
setDimension(Rect(0, 0, 365, 75));
}
@@ -121,6 +135,13 @@ void Setup_Joystick::action(const ActionEvent &event)
if (joystick != nullptr)
joystick->setNumber(mNamesDropDown->getSelected());
}
+ else if (source == mToleranceSlider)
+ {
+ const float tolerance = mToleranceSlider->getValue();
+ // TRANSLATORS: joystick settings tab label
+ mToleranceLabel->setCaption(_("joystick dead zone: ")
+ + strprintf("%.2f", tolerance));
+ }
else if (source == mDetectButton)
{
Joystick::detect();
@@ -130,36 +151,11 @@ void Setup_Joystick::action(const ActionEvent &event)
else
mNamesDropDown->setSelected(0);
}
- else
- {
- if (joystick == nullptr)
- return;
-
- if (joystick->isCalibrating())
- {
- // TRANSLATORS: joystick settings tab button
- mCalibrateButton->setCaption(_("Calibrate"));
- mCalibrateLabel->setCaption
- // TRANSLATORS: joystick settings tab label
- (_("Press the button to start calibration"));
- joystick->finishCalibration();
- }
- else
- {
- // TRANSLATORS: joystick settings tab button
- mCalibrateButton->setCaption(_("Stop"));
- mCalibrateLabel->setCaption(
- // TRANSLATORS: joystick settings tab label
- _("Rotate the stick and don't press buttons"));
- joystick->startCalibration();
- }
- }
}
void Setup_Joystick::setTempEnabled(const bool sel)
{
Joystick::setEnabled(sel);
- mCalibrateButton->setEnabled(sel);
if (joystick != nullptr)
{
if (sel)
@@ -186,6 +182,16 @@ void Setup_Joystick::apply()
config.setValue("joystickEnabled", Joystick::isEnabled());
- config.setValue("useInactiveJoystick", mUseInactiveCheckBox->isSelected());
- joystick->setUseInactive(mUseInactiveCheckBox->isSelected());
+ config.setValue("useHatForMovement",
+ mUseHatForMovementCheckBox->isSelected());
+ joystick->setUseHatForMovement(
+ mUseHatForMovementCheckBox->isSelected());
+ config.setValue("useInactiveJoystick",
+ mUseInactiveCheckBox->isSelected());
+ joystick->setUseInactive(
+ mUseInactiveCheckBox->isSelected());
+
+ float tolerance = mToleranceSlider->getValue();
+ config.setValue("joystickTolerance", tolerance);
+ joystick->setTolerance(tolerance);
}
diff --git a/src/gui/widgets/tabs/setup_joystick.h b/src/gui/widgets/tabs/setup_joystick.h
index 174cd82b2..2c138daf5 100644
--- a/src/gui/widgets/tabs/setup_joystick.h
+++ b/src/gui/widgets/tabs/setup_joystick.h
@@ -31,6 +31,7 @@ class CheckBox;
class DropDown;
class Label;
class NamesModel;
+class Slider;
class Setup_Joystick final : public SetupTab
{
@@ -50,12 +51,13 @@ class Setup_Joystick final : public SetupTab
void setTempEnabled(const bool sel);
private:
- Label *mCalibrateLabel A_NONNULLPOINTER;
- Button *mCalibrateButton A_NONNULLPOINTER;
Button *mDetectButton A_NONNULLPOINTER;
CheckBox *mJoystickEnabled A_NONNULLPOINTER;
NamesModel *mNamesModel A_NONNULLPOINTER;
DropDown *mNamesDropDown A_NONNULLPOINTER;
+ Label *mToleranceLabel A_NONNULLPOINTER;
+ Slider *mToleranceSlider A_NONNULLPOINTER;
+ CheckBox *mUseHatForMovementCheckBox A_NONNULLPOINTER;
CheckBox *mUseInactiveCheckBox A_NONNULLPOINTER;
bool mOriginalJoystickEnabled A_NONNULLPOINTER;
};
diff --git a/src/gui/windows/chatwindow.cpp b/src/gui/windows/chatwindow.cpp
index a3b777655..15363883f 100644
--- a/src/gui/windows/chatwindow.cpp
+++ b/src/gui/windows/chatwindow.cpp
@@ -1246,8 +1246,6 @@ WhisperTab *ChatWindow::addWhisperTab(const std::string &caption,
if ((gui != nullptr) && !playerRelations.isGoodName(nick))
ret->setLabelFont(gui->getSecureFont());
mWhispers[tempNick] = ret;
- if (config.getBoolValue("showChatHistory"))
- ret->loadFromLogFile(nick);
}
if (switchTo)
@@ -1330,8 +1328,6 @@ ChatTab *ChatWindow::addChannelTab(const std::string &name,
ret = new ChannelTab(this, name);
mChannels[tempName] = ret;
ret->setAllowHighlight(false);
- if (config.getBoolValue("showChatHistory"))
- ret->loadFromLogFile(name);
}
if (switchTo)
diff --git a/src/gui/windows/ministatuswindow.cpp b/src/gui/windows/ministatuswindow.cpp
index 4c2b2d376..e52a1a8d7 100644
--- a/src/gui/windows/ministatuswindow.cpp
+++ b/src/gui/windows/ministatuswindow.cpp
@@ -275,8 +275,6 @@ void MiniStatusWindow::statChanged(const AttributesT id A_UNUSED,
statusWindow->updateMPBar(mMpBar,
false);
}
- StatusWindow::updateJobBar(mJobBar,
- true);
}
void MiniStatusWindow::attributeChanged(const AttributesT id,
@@ -302,6 +300,11 @@ void MiniStatusWindow::attributeChanged(const AttributesT id,
StatusWindow::updateXPBar(mXpBar,
true);
break;
+ case Attributes::PLAYER_JOB_LEVEL:
+ case Attributes::PLAYER_JOB_EXP:
+ case Attributes::PLAYER_JOB_EXP_NEEDED:
+ StatusWindow::updateJobBar(mJobBar, true);
+ break;
case Attributes::TOTAL_WEIGHT:
case Attributes::MAX_WEIGHT:
StatusWindow::updateWeightBar(mWeightBar);
diff --git a/src/gui/windows/quitdialog.cpp b/src/gui/windows/quitdialog.cpp
index d1ceb1ad9..7ef2bc6e8 100644
--- a/src/gui/windows/quitdialog.cpp
+++ b/src/gui/windows/quitdialog.cpp
@@ -210,6 +210,7 @@ void QuitDialog::keyPressed(KeyEvent &event)
{
const InputActionT actionId = event.getActionId();
int dir = 0;
+ bool consume = true;
PRAGMA45(GCC diagnostic push)
PRAGMA45(GCC diagnostic ignored "-Wswitch-enum")
@@ -229,10 +230,14 @@ void QuitDialog::keyPressed(KeyEvent &event)
dir = 1;
break;
default:
+ consume = false;
break;
}
PRAGMA45(GCC diagnostic pop)
+ if (consume)
+ event.consume();
+
if (dir != 0)
{
STD_VECTOR<RadioButton*>::const_iterator it = mOptions.begin();
diff --git a/src/gui/windows/registerdialog.cpp b/src/gui/windows/registerdialog.cpp
index 40a0e472c..588ca0074 100644
--- a/src/gui/windows/registerdialog.cpp
+++ b/src/gui/windows/registerdialog.cpp
@@ -157,6 +157,12 @@ RegisterDialog::~RegisterDialog()
delete2(mWrongDataNoticeListener)
}
+void RegisterDialog::logic()
+{
+ mRegisterButton->setEnabled(canSubmit());
+ Window::logic();
+}
+
void RegisterDialog::action(const ActionEvent &event)
{
const std::string &eventId = event.getId();
@@ -289,11 +295,6 @@ void RegisterDialog::action(const ActionEvent &event)
void RegisterDialog::keyPressed(KeyEvent &event)
{
- if (event.isConsumed())
- {
- mRegisterButton->setEnabled(canSubmit());
- return;
- }
const InputActionT actionId = event.getActionId();
if (actionId == InputAction::GUI_CANCEL)
{
@@ -304,10 +305,6 @@ void RegisterDialog::keyPressed(KeyEvent &event)
{
action(ActionEvent(nullptr, mRegisterButton->getActionEventId()));
}
- else
- {
- mRegisterButton->setEnabled(canSubmit());
- }
}
bool RegisterDialog::canSubmit() const
diff --git a/src/gui/windows/registerdialog.h b/src/gui/windows/registerdialog.h
index 6249253f8..139739780 100644
--- a/src/gui/windows/registerdialog.h
+++ b/src/gui/windows/registerdialog.h
@@ -62,6 +62,8 @@ class RegisterDialog final : public Window,
void postInit() override;
+ void logic() override final;
+
/**
* Called when receiving actions from the widgets.
*/
diff --git a/src/gui/windows/updaterwindow.cpp b/src/gui/windows/updaterwindow.cpp
index 948ce5a17..2ed01f4f3 100644
--- a/src/gui/windows/updaterwindow.cpp
+++ b/src/gui/windows/updaterwindow.cpp
@@ -619,8 +619,7 @@ void UpdaterWindow::download()
const STD_VECTOR<std::string> &mirrors = settings.updateMirrors;
FOR_EACH (STD_VECTOR<std::string>::const_iterator, it, mirrors)
{
- mDownload->addMirror(pathJoin(*it,
- mCurrentFile));
+ mDownload->addMirror(urlJoin(*it, mCurrentFile));
}
}
}
diff --git a/src/input/inputmanager.cpp b/src/input/inputmanager.cpp
index a379e0e86..8cb10041e 100644
--- a/src/input/inputmanager.cpp
+++ b/src/input/inputmanager.cpp
@@ -416,8 +416,45 @@ std::string InputManager::getKeyStringLong(const InputActionT index) const
}
else if (key.type == InputType::JOYSTICK)
{
- // TRANSLATORS: long joystick button name. must be short.
- str = strprintf(_("JButton%d"), key.value + 1);
+ if (key.value < Joystick::MAX_BUTTONS)
+ {
+ // TRANSLATORS: joystick button name. must be short.
+ str = strprintf(_("JButton%d"), key.value + 1);
+ }
+ else if (key.value == Joystick::KEY_UP)
+ {
+ // TRANSLATORS: joystick up button. must be short.
+ str = _("JUp");
+ }
+ else if (key.value == Joystick::KEY_DOWN)
+ {
+ // TRANSLATORS: joystick down button. must be short.
+ str = _("JDown");
+ }
+ else if (key.value == Joystick::KEY_LEFT)
+ {
+ // TRANSLATORS: joystick left button. must be short.
+ str = _("JLeft");
+ }
+ else if (key.value == Joystick::KEY_RIGHT)
+ {
+ // TRANSLATORS: joystick right button. must be short.
+ str = _("JRight");
+ }
+ else if (key.value >= Joystick::KEY_NEGATIVE_AXIS_FIRST
+ && key.value < Joystick::KEY_POSITIVE_AXIS_FIRST)
+ {
+ // TRANSLATORS: joystick negative axis. must be short.
+ str = strprintf(_("JAxis%dMinus"),
+ key.value - Joystick::KEY_NEGATIVE_AXIS_FIRST);
+ }
+ else if (key.value >= Joystick::KEY_POSITIVE_AXIS_FIRST
+ && key.value < Joystick::KEY_END)
+ {
+ // TRANSLATORS: joystick positive axis. must be short.
+ str = strprintf(_("JAxis%dPlus"),
+ key.value - Joystick::KEY_POSITIVE_AXIS_FIRST);
+ }
}
if (!str.empty())
{
@@ -459,8 +496,45 @@ void InputManager::updateKeyString(const InputFunction &ki,
}
else if (key.type == InputType::JOYSTICK)
{
- // TRANSLATORS: short joystick button name. muse be very short
- str = strprintf(_("JB%d"), key.value + 1);
+ if (key.value < Joystick::MAX_BUTTONS)
+ {
+ // TRANSLATORS: joystick button name. must be very short
+ str = strprintf(_("JB%d"), key.value + 1);
+ }
+ else if (key.value == Joystick::KEY_UP)
+ {
+ // TRANSLATORS: joystick up button. must be very short
+ str = _("JUp");
+ }
+ else if (key.value == Joystick::KEY_DOWN)
+ {
+ // TRANSLATORS: joystick down button. must be very short
+ str = _("JDn");
+ }
+ else if (key.value == Joystick::KEY_LEFT)
+ {
+ // TRANSLATORS: joystick left button. must be very short
+ str = _("JLt");
+ }
+ else if (key.value == Joystick::KEY_RIGHT)
+ {
+ // TRANSLATORS: joystick right button. must be very short
+ str = _("JRt");
+ }
+ else if (key.value >= Joystick::KEY_NEGATIVE_AXIS_FIRST
+ && key.value < Joystick::KEY_POSITIVE_AXIS_FIRST)
+ {
+ // TRANSLATORS: joystick negative axis. must be very short.
+ str = strprintf(_("JA%d-"),
+ key.value - Joystick::KEY_NEGATIVE_AXIS_FIRST);
+ }
+ else if (key.value >= Joystick::KEY_POSITIVE_AXIS_FIRST
+ && key.value < Joystick::KEY_END)
+ {
+ // TRANSLATORS: joystick positive axis. must be very short.
+ str = strprintf(_("JA%d+"),
+ key.value - Joystick::KEY_POSITIVE_AXIS_FIRST);
+ }
}
if (!str.empty())
{
@@ -617,21 +691,7 @@ bool InputManager::handleEvent(const SDL_Event &restrict event) restrict2
BLOCK_END("InputManager::handleEvent")
return true;
}
-
keyboard.handleActivateKey(event);
- // send straight to gui for certain windows
-#ifndef DYECMD
- if ((quitDialog != nullptr) || TextDialog::isActive())
- {
- if (guiInput != nullptr)
- guiInput->pushInput(event);
- if (gui != nullptr)
- gui->handleInput();
- BLOCK_END("InputManager::handleEvent")
- return true;
- }
-#endif // DYECMD
-
break;
}
case SDL_KEYUP:
@@ -650,10 +710,13 @@ bool InputManager::handleEvent(const SDL_Event &restrict event) restrict2
break;
}
case SDL_JOYBUTTONDOWN:
+ case SDL_JOYHATMOTION:
+ case SDL_JOYAXISMOTION:
{
updateConditionMask(true);
// joystick.handleActicateButton(event);
- if (handleAssignKey(event, InputType::JOYSTICK))
+ if (joystick != nullptr && joystick->isActionEvent(event)
+ && handleAssignKey(event, InputType::JOYSTICK))
{
BLOCK_END("InputManager::handleEvent")
return true;
@@ -690,8 +753,16 @@ bool InputManager::handleEvent(const SDL_Event &restrict event) restrict2
guiInput->pushInput(event);
if (gui != nullptr)
{
- const bool res = gui->handleInput();
- if (res && event.type == SDL_KEYDOWN)
+ bool res = gui->handleInput();
+#ifndef DYECMD
+ // always treat keyboard input as handled if a text dialog is active
+ if (event.type == SDL_KEYDOWN && TextDialog::isActive())
+ res = true;
+#endif // DYECMD
+ const bool joystickActionEvent =
+ joystick != nullptr && joystick->isActionEvent(event);
+ // stop processing input if event is consumed by the gui
+ if (res && (event.type == SDL_KEYDOWN || joystickActionEvent))
{
BLOCK_END("InputManager::handleEvent")
return true;
@@ -724,6 +795,8 @@ bool InputManager::handleEvent(const SDL_Event &restrict event) restrict2
// break;
case SDL_JOYBUTTONDOWN:
+ case SDL_JOYHATMOTION:
+ case SDL_JOYAXISMOTION:
if ((joystick != nullptr) && joystick->validate())
{
if (triggerAction(joystick->getActionVector(event)))
@@ -1055,7 +1128,6 @@ InputActionT InputManager::getKeyIndex(const int value,
InputActionT InputManager::getActionByKey(const SDL_Event &restrict event)
const restrict2
{
- // for now support only keyboard events
if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
{
const InputActionT idx = keyboard.getActionId(event);
@@ -1065,6 +1137,15 @@ InputActionT InputManager::getActionByKey(const SDL_Event &restrict event)
return idx;
}
}
+ if (joystick != nullptr && joystick->isActionEvent(event))
+ {
+ const InputActionT idx = joystick->getActionId(event);
+ if (CAST_S32(idx) >= 0 &&
+ checkKey(&inputActionData[CAST_SIZE(idx)]))
+ {
+ return idx;
+ }
+ }
return InputAction::NO_VALUE;
}
diff --git a/src/input/joystick.cpp b/src/input/joystick.cpp
index 52d9a7525..ea1883ad0 100644
--- a/src/input/joystick.cpp
+++ b/src/input/joystick.cpp
@@ -47,21 +47,24 @@ bool Joystick::mInitialized = false;
Joystick::Joystick(const int no) :
mDirection(0),
+ mHatPosition(0),
mJoystick(nullptr),
- mUpTolerance(0),
- mDownTolerance(0),
- mLeftTolerance(0),
- mRightTolerance(0),
- mCalibrating(false),
+ mTolerance(0),
mNumber(no >= joystickCount ? joystickCount : no),
- mCalibrated(false),
+ mAxesNumber(MAX_AXES),
mButtonsNumber(MAX_BUTTONS),
+ mUseHatForMovement(true),
mUseInactive(false),
mHaveHats(false),
mKeyToAction(),
mKeyToId(),
mKeyTimeMap()
{
+ for (int i = 0; i < MAX_AXES; i++)
+ {
+ mIsTrigger[i] = false;
+ mAxesPositions[i] = 0;
+ }
for (int i = 0; i < MAX_BUTTONS; i++)
mActiveButtons[i] = false;
}
@@ -130,7 +133,9 @@ bool Joystick::open()
return false;
}
+ mAxesNumber = SDL_JoystickNumAxes(mJoystick);
mButtonsNumber = SDL_JoystickNumButtons(mJoystick);
+
logger->log("Joystick: %i ", mNumber);
#ifdef USE_SDL2
logger->log("Name: %s", SDL_JoystickName(mJoystick));
@@ -189,32 +194,31 @@ bool Joystick::open()
logger->log("Name: %s", SDL_JoystickName(mNumber));
#endif // USE_SDL2
- logger->log("Axes: %i ", SDL_JoystickNumAxes(mJoystick));
+ logger->log("Axes: %i ", mAxesNumber);
logger->log("Balls: %i", SDL_JoystickNumBalls(mJoystick));
logger->log("Hats: %i", SDL_JoystickNumHats(mJoystick));
logger->log("Buttons: %i", mButtonsNumber);
mHaveHats = (SDL_JoystickNumHats(mJoystick) > 0);
+ if (mAxesNumber > MAX_AXES)
+ mAxesNumber = mAxesNumber;
+
if (mButtonsNumber > MAX_BUTTONS)
mButtonsNumber = MAX_BUTTONS;
-#ifdef __SWITCH__
- config.setValue("joystick" + toString(mNumber) + "calibrated", true);
- config.setValue("leftTolerance" + toString(mNumber), -10000);
- config.setValue("rightTolerance" + toString(mNumber), 10000);
- config.setValue("upTolerance" + toString(mNumber), -10000);
- config.setValue("downTolerance" + toString(mNumber), 10000);
-#endif
- mCalibrated = config.getValueBool("joystick"
- + toString(mNumber) + "calibrated", false);
-
- mUpTolerance = config.getIntValue("upTolerance" + toString(mNumber));
- mDownTolerance = config.getIntValue("downTolerance" + toString(mNumber));
- mLeftTolerance = config.getIntValue("leftTolerance" + toString(mNumber));
- mRightTolerance = config.getIntValue("rightTolerance" + toString(mNumber));
+ mTolerance = config.getFloatValue("joystickTolerance");
+ mUseHatForMovement = config.getBoolValue("useHatForMovement");
mUseInactive = config.getBoolValue("useInactiveJoystick");
+ for (int i = 0; i < mAxesNumber; i++)
+ {
+ // heuristic to detect controller triggers.
+ // their resting position is at SDL_JOYSTICK_AXIS_MIN = -32768
+ if (SDL_JoystickGetAxis(mJoystick, i) == SDL_JOYSTICK_AXIS_MIN)
+ mIsTrigger[i] = true;
+ }
+
return true;
}
@@ -245,15 +249,7 @@ void Joystick::setNumber(const int n)
void Joystick::logic()
{
BLOCK_START("Joystick::logic")
- // When calibrating, don't bother the outside with our state
- if (mCalibrating)
- {
- doCalibration();
- BLOCK_END("Joystick::logic")
- return;
- }
-
- if (!mEnabled || !mCalibrated)
+ if (!mEnabled)
{
BLOCK_END("Joystick::logic")
return;
@@ -264,18 +260,28 @@ void Joystick::logic()
if (mUseInactive ||
settings.inputFocused != KeyboardFocus::Unfocused)
{
+ for (int i = 0; i < mAxesNumber; i++)
+ {
+ int position = SDL_JoystickGetAxis(mJoystick, i);
+ // transform range [SDL_JOYSTICK_AXIS_MIN, SDL_JOYSTICK_AXIS_MAX]
+ // to [0, SDL_JOYSTICK_AXIS_MAX]
+ if (mIsTrigger[i])
+ position = (position - SDL_JOYSTICK_AXIS_MIN) / 2;
+ mAxesPositions[i] = position;
+ }
+
// X-Axis
- int position = SDL_JoystickGetAxis(mJoystick, 0);
- if (position >= mRightTolerance)
+ int position = mAxesPositions[0];
+ if (position >= mTolerance * SDL_JOYSTICK_AXIS_MAX)
mDirection |= RIGHT;
- else if (position <= mLeftTolerance)
+ else if (position <= mTolerance * SDL_JOYSTICK_AXIS_MIN)
mDirection |= LEFT;
// Y-Axis
- position = SDL_JoystickGetAxis(mJoystick, 1);
- if (position <= mUpTolerance)
+ position = mAxesPositions[1];
+ if (position <= mTolerance * SDL_JOYSTICK_AXIS_MIN)
mDirection |= UP;
- else if (position >= mDownTolerance)
+ else if (position >= mTolerance * SDL_JOYSTICK_AXIS_MAX)
mDirection |= DOWN;
#ifdef DEBUG_JOYSTICK
@@ -287,18 +293,21 @@ void Joystick::logic()
logger->log("axis 4 pos: %d", SDL_JoystickGetAxis(mJoystick, 4));
#endif // DEBUG_JOYSTICK
- if ((mDirection == 0U) && mHaveHats)
+ if (mHaveHats)
{
// reading only hat 0
const uint8_t hat = SDL_JoystickGetHat(mJoystick, 0);
+ mHatPosition = 0;
if ((hat & SDL_HAT_RIGHT) != 0)
- mDirection |= RIGHT;
+ mHatPosition |= RIGHT;
else if ((hat & SDL_HAT_LEFT) != 0)
- mDirection |= LEFT;
+ mHatPosition |= LEFT;
if ((hat & SDL_HAT_UP) != 0)
- mDirection |= UP;
+ mHatPosition |= UP;
else if ((hat & SDL_HAT_DOWN) != 0)
- mDirection |= DOWN;
+ mHatPosition |= DOWN;
+ if ((mDirection == 0U) && mUseHatForMovement)
+ mDirection = mHatPosition;
}
// Buttons
@@ -316,52 +325,42 @@ void Joystick::logic()
}
else
{
+ mHatPosition = 0;
+ for (int i = 0; i < mAxesNumber; i++)
+ mAxesPositions[i] = 0;
for (int i = 0; i < mButtonsNumber; i++)
mActiveButtons[i] = false;
}
BLOCK_END("Joystick::logic")
}
-void Joystick::startCalibration()
-{
- mUpTolerance = 0;
- mDownTolerance = 0;
- mLeftTolerance = 0;
- mRightTolerance = 0;
- mCalibrating = true;
-}
-
-void Joystick::doCalibration()
+bool Joystick::buttonPressed(const int no) const
{
- // X-Axis
- int position = SDL_JoystickGetAxis(mJoystick, 0);
- if (position > mRightTolerance)
- mRightTolerance = position;
- else if (position < mLeftTolerance)
- mLeftTolerance = position;
-
- // Y-Axis
- position = SDL_JoystickGetAxis(mJoystick, 1);
- if (position > mDownTolerance)
- mDownTolerance = position;
- else if (position < mUpTolerance)
- mUpTolerance = position;
-}
+ if (!mEnabled)
+ return false;
+ const int button = getButton(no);
+ if (button >= 0)
+ {
+ if (button < mButtonsNumber)
+ return mActiveButtons[button];
+ if (button == KEY_UP)
+ return (mHatPosition & UP) != 0;
+ if (button == KEY_DOWN)
+ return (mHatPosition & DOWN) != 0;
+ if (button == KEY_LEFT)
+ return (mHatPosition & LEFT) != 0;
+ if (button == KEY_RIGHT)
+ return (mHatPosition & RIGHT) != 0;
+ }
+ const int naxis = getNegativeAxis(no);
+ if (naxis >= 0)
+ return mAxesPositions[naxis] < mTolerance * SDL_JOYSTICK_AXIS_MIN;
-void Joystick::finishCalibration()
-{
- mCalibrated = true;
- mCalibrating = false;
- config.setValue("joystick" + toString(mNumber) + "calibrated", true);
- config.setValue("leftTolerance" + toString(mNumber), mLeftTolerance);
- config.setValue("rightTolerance" + toString(mNumber), mRightTolerance);
- config.setValue("upTolerance" + toString(mNumber), mUpTolerance);
- config.setValue("downTolerance" + toString(mNumber), mDownTolerance);
-}
+ const int paxis = getPositiveAxis(no);
+ if (paxis >= 0)
+ return mAxesPositions[paxis] > mTolerance * SDL_JOYSTICK_AXIS_MAX;
-bool Joystick::buttonPressed(const unsigned char no) const
-{
- return (mEnabled && no < MAX_BUTTONS) ? mActiveButtons[no] : false;
+ return false;
}
void Joystick::getNames(STD_VECTOR <std::string> &names)
@@ -377,33 +376,128 @@ void Joystick::update()
mKeyTimeMap, InputType::JOYSTICK);
}
+bool Joystick::isActionEvent(const SDL_Event &event)
+{
+ return getButtonFromEvent(event) >= 0;
+}
+
KeysVector *Joystick::getActionVector(const SDL_Event &event)
{
const int i = getButtonFromEvent(event);
-
- if (i < 0 || i >= mButtonsNumber)
- return nullptr;
-// logger->log("button triggerAction: %d", i);
- if (mKeyToAction.find(i) != mKeyToAction.end())
- return &mKeyToAction[i];
- return nullptr;
+ return getActionVectorByKey(i);
}
KeysVector *Joystick::getActionVectorByKey(const int i)
{
- if (i < 0 || i >= mButtonsNumber)
+ if (getButton(i) < 0
+ && getNegativeAxis(i) < 0
+ && getPositiveAxis(i) < 0)
+ {
return nullptr;
+ }
// logger->log("button triggerAction: %d", i);
- if (mKeyToAction.find(i) != mKeyToAction.end())
- return &mKeyToAction[i];
+
+ KeyToActionMapIter it = mKeyToAction.find(i);
+ if (it != mKeyToAction.end())
+ return &it->second;
+
return nullptr;
}
+InputActionT Joystick::getActionId(const SDL_Event &event)
+{
+ const int i = getButtonFromEvent(event);
+ if (i < 0)
+ return InputAction::NO_VALUE;
+
+ KeyToIdMapIter it = mKeyToId.find(i);
+ if (it != mKeyToId.end())
+ return it->second;
+
+ return InputAction::NO_VALUE;
+}
+
int Joystick::getButtonFromEvent(const SDL_Event &event) const
{
- if (event.jbutton.which != mNumber)
+ if (event.type == SDL_JOYBUTTONDOWN)
+ {
+ if (event.jbutton.which != mNumber)
+ return -1;
+ return event.jbutton.button;
+ }
+ if (!mUseHatForMovement && event.type == SDL_JOYHATMOTION)
+ {
+ // reading only hat 0
+ if (event.jhat.which != mNumber || event.jhat.hat != 0)
+ return -1;
+ const int value = event.jhat.value;
+ // SDL reports new hat position, not when d-pad button is pressed.
+ // because of that we have to compare it to previously known state.
+ if ((mHatPosition & UP) == 0 && (value & SDL_HAT_UP) != 0)
+ return KEY_UP;
+ if ((mHatPosition & DOWN) == 0 && (value & SDL_HAT_DOWN) != 0)
+ return KEY_DOWN;
+ if ((mHatPosition & LEFT) == 0 && (value & SDL_HAT_LEFT) != 0)
+ return KEY_LEFT;
+ if ((mHatPosition & RIGHT) == 0 && (value & SDL_HAT_RIGHT) != 0)
+ return KEY_RIGHT;
+ }
+ if (event.type == SDL_JOYAXISMOTION)
+ {
+ if (event.jaxis.which != mNumber)
+ return -1;
+ const int axis = event.jaxis.axis;
+ if (axis < RESERVED_AXES)
+ return -1;
+ int position = event.jaxis.value;
+ // transform range [SDL_JOYSTICK_AXIS_MIN, SDL_JOYSTICK_AXIS_MAX]
+ // to [0, SDL_JOYSTICK_AXIS_MAX]
+ if (mIsTrigger[axis])
+ position = (position - SDL_JOYSTICK_AXIS_MIN) / 2;
+ if (position < mTolerance * SDL_JOYSTICK_AXIS_MIN
+ && mAxesPositions[axis] > mTolerance * SDL_JOYSTICK_AXIS_MIN)
+ return KEY_NEGATIVE_AXIS_FIRST + axis;
+ if (position > mTolerance * SDL_JOYSTICK_AXIS_MAX
+ && mAxesPositions[axis] < mTolerance * SDL_JOYSTICK_AXIS_MAX)
+ return KEY_POSITIVE_AXIS_FIRST + axis;
+ }
+ return -1;
+}
+
+int Joystick::getButton(const int key) const
+{
+ if (key < 0
+ || (mButtonsNumber <= key && key < MAX_BUTTONS)
+ || (mUseHatForMovement && key >= MAX_BUTTONS)
+ || key >= KEY_NEGATIVE_AXIS_FIRST)
+ {
+ return -1;
+ }
+ return key;
+}
+
+int Joystick::getNegativeAxis(const int key) const
+{
+ if (key < KEY_NEGATIVE_AXIS_FIRST || key >= KEY_POSITIVE_AXIS_FIRST)
+ return -1;
+
+ const int axis = key - KEY_NEGATIVE_AXIS_FIRST;
+ if (axis < RESERVED_AXES || axis >= mAxesNumber)
+ return -1;
+
+ return axis;
+}
+
+int Joystick::getPositiveAxis(const int key) const
+{
+ if (key < KEY_POSITIVE_AXIS_FIRST || key >= KEY_END)
return -1;
- return event.jbutton.button;
+
+ const int axis = key - KEY_POSITIVE_AXIS_FIRST;
+ if (axis < RESERVED_AXES || axis >= mAxesNumber)
+ return -1;
+
+ return axis;
}
bool Joystick::isActionActive(const InputActionT index) const
@@ -417,19 +511,14 @@ bool Joystick::isActionActive(const InputActionT index) const
const InputItem &val = key.values[i];
if (val.type != InputType::JOYSTICK)
continue;
- const int value = val.value;
- if (value >= 0 && value < mButtonsNumber)
- {
- if (mActiveButtons[value])
- return true;
- }
+ return buttonPressed(val.value);
}
return false;
}
bool Joystick::validate() const
{
- if (mCalibrating || !mEnabled || !mCalibrated)
+ if (!mEnabled)
return false;
return mUseInactive ||
@@ -441,14 +530,8 @@ void Joystick::handleRepeat(const int time)
BLOCK_START("Joystick::handleRepeat")
FOR_EACH (KeyTimeMapIter, it, mKeyTimeMap)
{
- bool repeat(false);
const int key = (*it).first;
- if (key >= 0 && key < mButtonsNumber)
- {
- if (mActiveButtons[key])
- repeat = true;
- }
- if (repeat)
+ if (buttonPressed(key))
{
int &keyTime = (*it).second;
if (time > keyTime && abs(time - keyTime)
diff --git a/src/input/joystick.h b/src/input/joystick.h
index a3c129950..49c4e553a 100644
--- a/src/input/joystick.h
+++ b/src/input/joystick.h
@@ -31,6 +31,15 @@ PRAGMA48(GCC diagnostic ignored "-Wshadow")
#include <SDL_events.h>
PRAGMA48(GCC diagnostic pop)
+// defined first in SDL 2.0.6
+// not available on older distros
+#ifndef SDL_JOYSTICK_AXIS_MIN
+#define SDL_JOYSTICK_AXIS_MIN -32768
+#endif
+#ifndef SDL_JOYSTICK_AXIS_MAX
+#define SDL_JOYSTICK_AXIS_MAX 32767
+#endif
+
class Joystick final
{
public:
@@ -42,6 +51,27 @@ class Joystick final
MAX_BUTTONS = 64
};
+ enum
+ {
+ RESERVED_AXES = 2, // reserved for movement
+ MAX_AXES = 8 // number of axes we can handle
+ };
+
+ /**
+ * Additional "buttons" for hat 0 (d-pad),
+ * sticks and triggers.
+ */
+ enum
+ {
+ KEY_UP = MAX_BUTTONS,
+ KEY_DOWN,
+ KEY_LEFT,
+ KEY_RIGHT,
+ KEY_NEGATIVE_AXIS_FIRST,
+ KEY_POSITIVE_AXIS_FIRST = KEY_NEGATIVE_AXIS_FIRST + MAX_AXES,
+ KEY_END = KEY_POSITIVE_AXIS_FIRST + MAX_AXES
+ };
+
/**
* Directions, to be used as bitmask values.
*/
@@ -98,14 +128,7 @@ class Joystick final
*/
void logic();
- void startCalibration();
-
- void finishCalibration();
-
- bool isCalibrating() const noexcept2 A_WARN_UNUSED
- { return mCalibrating; }
-
- bool buttonPressed(const unsigned char no) const A_WARN_UNUSED;
+ bool buttonPressed(const int no) const A_WARN_UNUSED;
bool isUp() const noexcept2 A_WARN_UNUSED
{ return mEnabled && ((mDirection & UP) != 0); }
@@ -122,15 +145,25 @@ class Joystick final
int getNumber() const noexcept2 A_WARN_UNUSED
{ return mNumber; }
+ void setTolerance(const float tolerance)
+ { mTolerance = tolerance; }
+
+ void setUseHatForMovement(const bool b)
+ { mUseHatForMovement = b; }
+
void setUseInactive(const bool b)
{ mUseInactive = b; }
void update();
+ bool isActionEvent(const SDL_Event &event) A_WARN_UNUSED;
+
KeysVector *getActionVector(const SDL_Event &event) A_WARN_UNUSED;
KeysVector *getActionVectorByKey(const int i) A_WARN_UNUSED;
+ InputActionT getActionId(const SDL_Event &event) A_WARN_UNUSED;
+
int getButtonFromEvent(const SDL_Event &event) const A_WARN_UNUSED;
bool isActionActive(const InputActionT index) const A_WARN_UNUSED;
@@ -144,18 +177,18 @@ class Joystick final
protected:
unsigned char mDirection;
+ unsigned char mHatPosition;
+ int mAxesPositions[MAX_AXES];
+ bool mIsTrigger[MAX_AXES];
bool mActiveButtons[MAX_BUTTONS];
SDL_Joystick *mJoystick;
- int mUpTolerance;
- int mDownTolerance;
- int mLeftTolerance;
- int mRightTolerance;
- bool mCalibrating;
+ float mTolerance;
int mNumber;
- bool mCalibrated;
+ int mAxesNumber;
int mButtonsNumber;
+ bool mUseHatForMovement;
bool mUseInactive;
bool mHaveHats;
@@ -172,7 +205,11 @@ class Joystick final
static bool mInitialized;
static int joystickCount;
- void doCalibration();
+ int getButton(const int key) const A_WARN_UNUSED;
+
+ int getNegativeAxis(const int key) const A_WARN_UNUSED;
+
+ int getPositiveAxis(const int key) const A_WARN_UNUSED;
};
extern Joystick *joystick;
diff --git a/src/net/ea/partyrecv.cpp b/src/net/ea/partyrecv.cpp
index 370cfed9c..53cb0227e 100644
--- a/src/net/ea/partyrecv.cpp
+++ b/src/net/ea/partyrecv.cpp
@@ -226,8 +226,6 @@ void PartyRecv::processPartyUpdateCoords(Net::MessageIn &msg)
void PartyRecv::createTab()
{
partyTab = new PartyTab(chatWindow);
- if (config.getBoolValue("showChatHistory"))
- partyTab->loadFromLogFile("#Party");
}
} // namespace Ea
diff --git a/src/net/eathena/clanrecv.cpp b/src/net/eathena/clanrecv.cpp
index 9ecb860a9..c686796dd 100644
--- a/src/net/eathena/clanrecv.cpp
+++ b/src/net/eathena/clanrecv.cpp
@@ -125,8 +125,6 @@ void ClanRecv::createTab()
if (clanTab != nullptr)
return;
clanTab = new ClanTab(chatWindow);
- if (config.getBoolValue("showChatHistory"))
- clanTab->loadFromLogFile("#Clan");
}
} // namespace EAthena
diff --git a/src/net/eathena/guildrecv.cpp b/src/net/eathena/guildrecv.cpp
index 74b8d9b8d..3d402c5b9 100644
--- a/src/net/eathena/guildrecv.cpp
+++ b/src/net/eathena/guildrecv.cpp
@@ -698,8 +698,6 @@ void GuildRecv::processGuildPositionInfo(Net::MessageIn &msg)
if ((guildTab == nullptr) && (chatWindow != nullptr))
{
guildTab = new GuildTab(chatWindow);
- if (config.getBoolValue("showChatHistory"))
- guildTab->loadFromLogFile("#Guild");
if (localPlayer != nullptr)
localPlayer->addGuild(taGuild);
guildHandler->memberList();
diff --git a/src/net/eathena/inventoryhandler.cpp b/src/net/eathena/inventoryhandler.cpp
index 3911c63fa..19197c851 100644
--- a/src/net/eathena/inventoryhandler.cpp
+++ b/src/net/eathena/inventoryhandler.cpp
@@ -572,7 +572,7 @@ void InventoryHandler::selectEgg(const Item *const item) const
int InventoryHandler::convertFromServerSlot(const int serverSlot) const
{
- if (serverSlot < 0 || serverSlot >= 17)
+ if (serverSlot < 0 || serverSlot > 17)
return 0;
return CAST_S32(EQUIP_CONVERT[serverSlot]);
diff --git a/src/net/eathena/packetsin.inc b/src/net/eathena/packetsin.inc
index 443c583c0..2a8e26264 100644
--- a/src/net/eathena/packetsin.inc
+++ b/src/net/eathena/packetsin.inc
@@ -84,6 +84,7 @@ packet(SMSG_CHAR_DELETE_SUCCEEDED, 0x006f, 2, &Ea::CharServerRecv::pro
packet(SMSG_CHAR_LOGIN, 0x006b, -1, &CharServerRecv::processCharLogin, 0);
packet(SMSG_CHAR_LOGIN2, 0x082d, -1, &CharServerRecv::processCharLogin2, 0);
packet(SMSG_CHAR_LOGIN_ERROR, 0x006c, 3, &Ea::CharServerRecv::processCharLoginError, 0);
+packet(SMSG_CHAR_PASSWORD_RESPONSE, 0x0062, 3, &LoginRecv::processCharPasswordResponse, 0);
packet(SMSG_CHAR_MAP_INFO, 0x0071, 28, &CharServerRecv::processCharMapInfo, 0);
packet(SMSG_CHAR_PINCODE_STATUS, 0x08b9, 12, &CharServerRecv::processPincodeStatus, 0);
packet(SMSG_CHAR_PINCODE_MAKE_STATUS, 0x08bb, 8, &CharServerRecv::processPincodeMakeStatus, 0);
@@ -1006,9 +1007,6 @@ if (serverVersion > 0)
packet2(SMSG_QUEST_LIST2, 0x0b23, -1, &QuestRecv::processAddQuests2, 0);
packet2(SMSG_QUEST_ADD2, 0x0b24, 23, &QuestRecv::processAddQuest2, 0);
packet2(SMSG_PLAYER_ATTRS, 0x0b25, -1, &PlayerRecv::processPlayerAttrs, 0);
-
- // char server
- packet2(SMSG_CHAR_PASSWORD_RESPONSE, 0x0062, 3, &LoginRecv::processCharPasswordResponse, 0);
}
// 20150225 main
diff --git a/src/net/tmwa/guildmanager.cpp b/src/net/tmwa/guildmanager.cpp
index f00e444db..52c056de6 100644
--- a/src/net/tmwa/guildmanager.cpp
+++ b/src/net/tmwa/guildmanager.cpp
@@ -234,8 +234,6 @@ void GuildManager::createTab(Guild *const guild)
if (mTab == nullptr)
{
mTab = new EmulateGuildTab(chatWindow);
- if (config.getBoolValue("showChatHistory"))
- mTab->loadFromLogFile("#Guild");
if (localPlayer != nullptr)
localPlayer->addGuild(guild);
}
diff --git a/src/net/tmwa/inventoryhandler.cpp b/src/net/tmwa/inventoryhandler.cpp
index a438c2602..076d365f1 100644
--- a/src/net/tmwa/inventoryhandler.cpp
+++ b/src/net/tmwa/inventoryhandler.cpp
@@ -34,14 +34,13 @@
#include "debug.h"
-// missing EQUIP_RING1_SLOT
const EquipSlot::Type EQUIP_CONVERT[] =
{
EquipSlot::PROJECTILE_SLOT, // 0 0
EquipSlot::FEET_SLOT, // 1 SPRITE_HAIR
EquipSlot::LEGS_SLOT, // 2 SPRITE_WEAPON
EquipSlot::TORSO_SLOT, // 3 SPRITE_HEAD_BOTTOM
- EquipSlot::PROJECTILE_SLOT, // 4 0
+ EquipSlot::RING1_SLOT, // 4 SPRITE_HEAD_TOP
EquipSlot::NECK_SLOT, // 5 SPRITE_RING
EquipSlot::PROJECTILE_SLOT, // 6 0
EquipSlot::HEAD_SLOT, // 7 SPRITE_CLOTHES_COLOR
diff --git a/src/net/tmwa/loginrecv.cpp b/src/net/tmwa/loginrecv.cpp
index a11888b9d..aa9b89fb9 100644
--- a/src/net/tmwa/loginrecv.cpp
+++ b/src/net/tmwa/loginrecv.cpp
@@ -62,34 +62,31 @@ void LoginRecv::processServerVersion(Net::MessageIn &msg)
const uint8_t b2 = msg.readUInt8("b2");
const uint8_t b3 = msg.readUInt8("b3");
msg.readUInt8("b4");
+ const unsigned int options = msg.readInt32("options");
+
+ Ea::LoginRecv::mRegistrationEnabled =
+ ((options & FLAG_REGISTRATION) != 0U);
+
+ serverVersion = 0;
+
if (b1 == 255)
{ // old TMWA
- const unsigned int options = msg.readInt32("options");
- Ea::LoginRecv::mRegistrationEnabled =
- ((options & FLAG_REGISTRATION) != 0U);
- serverVersion = 0;
tmwServerVersion = 0;
}
else if (b1 >= 0x0d)
{ // new TMWA
- const unsigned int options = msg.readInt32("options");
- Ea::LoginRecv::mRegistrationEnabled =
- ((options & FLAG_REGISTRATION) != 0U);
- serverVersion = 0;
tmwServerVersion = (b1 << 16) | (b2 << 8) | b3;
}
else
{ // eAthena
- const unsigned int options = msg.readInt32("options");
- Ea::LoginRecv::mRegistrationEnabled =
- ((options & FLAG_REGISTRATION) != 0U);
- serverVersion = 0;
tmwServerVersion = 0;
}
+
if (tmwServerVersion > 0)
- logger->log("Tmw server version: x%06x", tmwServerVersion);
+ logger->log("TMW server version: 0x%06x", tmwServerVersion);
else
logger->log("Server without version");
+
updateProtocol();
if (client->getState() != State::LOGIN)
diff --git a/tools/ci/jobs/mplint.sh b/tools/ci/jobs/mplint.sh
index 573cd1c85..60422e5f6 100755
--- a/tools/ci/jobs/mplint.sh
+++ b/tools/ci/jobs/mplint.sh
@@ -1,29 +1,18 @@
#!/usr/bin/env bash
-export CC=gcc
-export CXX=g++
-
-if [ "$NEWCC" != "" ]; then
- export CC="$NEWCC"
-fi
-if [ "$NEWCXX" != "" ]; then
- export CXX="$NEWCXX"
-fi
+set -e # Fail if any command fails
+set -u # Fail if any variable is unset when used
export LOGFILE=mplint_po.log
-
source ./tools/ci/scripts/init.sh
-export CXXFLAGS="-std=gnu++11"
+rm -rf mplint || true
+tools/ci/scripts/retry.sh wget -O mplint-release.zip "$MPLINT_PACKAGE_URL"
+unzip mplint-release.zip
-do_init
+read mplint_commit < mplint-version.txt
+printf "Using mplint: %s\n" "$mplint_commit"
-rm -rf mplint || true
-gitclone https://git.themanaworld.org/mana mplint.git
-cd mplint
-run_configure_simple
-run_make
-cd ..
echo " " >config.h
for task in "$@"; do
run_mplint $task
diff --git a/tools/ci/scripts/exit.sh b/tools/ci/scripts/exit.sh
index 1f13618c1..5c63a1d1b 100755
--- a/tools/ci/scripts/exit.sh
+++ b/tools/ci/scripts/exit.sh
@@ -1,3 +1,3 @@
#!/usr/bin/env bash
-rm $ERRFILE
+rm -f "$ERRFILE"
diff --git a/tools/ci/scripts/init.sh b/tools/ci/scripts/init.sh
index 9512e9b66..ed25a59e8 100755
--- a/tools/ci/scripts/init.sh
+++ b/tools/ci/scripts/init.sh
@@ -3,7 +3,7 @@
export dir=$(pwd)
export ERRFILE=${dir}/logs/${LOGFILE}
-rm ${ERRFILE}
+rm -f "$ERRFILE"
function do_init {
$CC --version
@@ -104,11 +104,11 @@ function check_error {
}
function run_configure_simple {
- rm $ERRFILE
+ rm -f "$ERRFILE"
echo "autoreconf -i"
autoreconf -i 2>$ERRFILE
check_error $?
- rm $ERRFILE
+ rm -f "$ERRFILE"
echo "./configure $*"
./configure $* 2>$ERRFILE
check_error $?
@@ -117,14 +117,14 @@ function run_configure_simple {
function run_configure {
run_configure_simple $*
- rm $ERRFILE
+ rm -f "$ERRFILE"
cd po
echo "make update-gmo"
make update-gmo 2>$ERRFILE
check_error $?
cd ..
- rm $ERRFILE
+ rm -f "$ERRFILE"
cd po
echo "make update-po"
make update-po 2>$ERRFILE
@@ -133,14 +133,14 @@ function run_configure {
}
function run_cmake {
- rm $ERRFILE
+ rm -f "$ERRFILE"
echo "cmake ."
cmake . 2>$ERRFILE
check_error $?
}
function run_make {
- rm $ERRFILE
+ rm -f "$ERRFILE"
if [ "$JOBS" == "" ]; then
export JOBS=2
echo "No JOBS defined"
@@ -153,7 +153,7 @@ function run_make {
}
function run_make_check {
- rm $ERRFILE
+ rm -f "$ERRFILE"
if [ "$JOBS" == "" ]; then
export JOBS=2
echo "No JOBS defined"
@@ -211,7 +211,7 @@ function run_check_warnings {
}
function run_h {
- rm $ERRFILE
+ rm -f "$ERRFILE"
echo "$CC -c -x c++ $* $includes */*/*/*/*.h */*/*/*.h */*/*.h */*.h *.h"
$CC -c -x c++ $* $includes */*/*/*/*.h */*/*/*.h */*/*.h */*.h *.h 2>$ERRFILE
if [[ -s "$ERRFILE" ]]; then
@@ -221,7 +221,7 @@ function run_h {
}
function run_tarball {
- rm $ERRFILE
+ rm -f "$ERRFILE"
echo "make dist-xz"
make dist-xz 2>$ERRFILE
check_error $?
@@ -234,14 +234,17 @@ function run_tarball {
}
function run_mplint {
- rm $ERRFILE
- echo "mplint/src/mplint $*"
- mplint/src/mplint "$@" \
- | grep -v \
- -e "src/unittests/doctest.h" \
- -e "src/unittests/catch.hpp" \
- -e "src/debug/" \
- > "$ERRFILE"
+ rm -f "$ERRFILE"
+ echo "\$ ./mplint $*"
+
+ ./mplint "$@" > "$ERRFILE.unfiltered"
+
+ # if grep does not find any messages, it exits non-zero
+ grep -v \
+ -e "src/unittests/doctest.h" \
+ -e "src/unittests/catch.hpp" \
+ -e "src/debug/" \
+ < "$ERRFILE.unfiltered" > "$ERRFILE" || true
run_check_warnings
}