GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/ea/playerrecv.cpp Lines: 1 109 0.9 %
Date: 2017-11-29 Branches: 0 81 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2004-2009  The Mana World Development Team
4
 *  Copyright (C) 2009-2010  The Mana Developers
5
 *  Copyright (C) 2011-2017  The ManaPlus Developers
6
 *
7
 *  This file is part of The ManaPlus Client.
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include "net/ea/playerrecv.h"
24
25
#include "game.h"
26
#include "notifymanager.h"
27
#include "settings.h"
28
#include "soundmanager.h"
29
30
#include "being/localplayer.h"
31
#include "being/playerinfo.h"
32
33
#include "const/net/nostat.h"
34
35
#include "enums/resources/notifytypes.h"
36
37
#include "gui/viewport.h"
38
39
#include "gui/windows/statuswindow.h"
40
41
#include "input/inputmanager.h"
42
43
#include "resources/map/map.h"
44
45
#include "net/playerhandler.h"
46
47
#include "utils/stdmove.h"
48
#include "utils/stringutils.h"
49
50
#include "debug.h"
51
52
// Max. distance we are willing to scroll after a teleport;
53
// everything beyond will reset the port hard.
54
static const int MAP_TELEPORT_SCROLL_DISTANCE = 8;
55
56
namespace Ea
57
{
58
59
void PlayerRecv::processPlayerWarp(Net::MessageIn &msg)
60
{
61
    BLOCK_START("PlayerRecv::processPlayerWarp")
62
    std::string mapPath = msg.readString(16, "map name");
63
    int x = msg.readInt16("x");
64
    int y = msg.readInt16("y");
65
66
    logger->log("Warping to %s (%d, %d)", mapPath.c_str(), x, y);
67
68
    if (localPlayer == nullptr)
69
        logger->log1("SMSG_PLAYER_WARP localPlayer null");
70
71
    /*
72
      * We must clear the local player's target *before* the call
73
      * to changeMap, as it deletes all beings.
74
      */
75
    if (localPlayer != nullptr)
76
        localPlayer->stopAttack();
77
78
    Game *const game = Game::instance();
79
    if (game == nullptr)
80
    {
81
        BLOCK_END("PlayerRecv::processPlayerWarp")
82
        return;
83
    }
84
85
    const std::string &currentMapName = game->getCurrentMapName();
86
    const bool sameMap = (currentMapName == mapPath);
87
88
    // Switch the actual map, deleting the previous one if necessary
89
    mapPath = mapPath.substr(0, mapPath.rfind('.'));
90
    game->changeMap(mapPath);
91
92
    int scrollOffsetX = 0;
93
    int scrollOffsetY = 0;
94
95
    if (localPlayer != nullptr)
96
    {
97
        const Map *const map = game->getCurrentMap();
98
        if (map != nullptr)
99
        {
100
            if (x >= map->getWidth())
101
                x = map->getWidth() - 1;
102
            if (y >= map->getHeight())
103
                y = map->getHeight() - 1;
104
            if (x < 0)
105
                x = 0;
106
            if (y < 0)
107
                y = 0;
108
            /* Scroll if neccessary */
109
            if (!sameMap
110
                || (abs(x - localPlayer->getTileX())
111
                > MAP_TELEPORT_SCROLL_DISTANCE)
112
                || (abs(y - localPlayer->getTileY())
113
                > MAP_TELEPORT_SCROLL_DISTANCE))
114
            {
115
                scrollOffsetX = (x - localPlayer->getTileX())
116
                    * map->getTileWidth();
117
                scrollOffsetY = (y - localPlayer->getTileY())
118
                    * map->getTileHeight();
119
            }
120
        }
121
122
        localPlayer->setAction(BeingAction::STAND, 0);
123
        localPlayer->setTileCoords(x, y);
124
        localPlayer->navigateClean();
125
        localPlayer->reset();
126
    }
127
128
    logger->log("Adjust scrolling by %d:%d", scrollOffsetX, scrollOffsetY);
129
130
    if (viewport != nullptr)
131
    {
132
        viewport->returnCamera();
133
        viewport->scrollBy(scrollOffsetX, scrollOffsetY);
134
    }
135
    BLOCK_END("PlayerRecv::processPlayerWarp")
136
}
137
138
void PlayerRecv::processPlayerStatUpdate1(Net::MessageIn &msg)
139
{
140
    BLOCK_START("PlayerRecv::processPlayerStatUpdate1")
141
    const int type = msg.readInt16("type");
142
    const int value = msg.readInt32("value");
143
    if (localPlayer == nullptr)
144
    {
145
        BLOCK_END("PlayerRecv::processPlayerStatUpdate1")
146
        return;
147
    }
148
149
    playerHandler->setStat(msg, type, value, NoStat, Notify_true);
150
    BLOCK_END("PlayerRecv::processPlayerStatUpdate1")
151
}
152
153
void PlayerRecv::processPlayerStatUpdate2(Net::MessageIn &msg)
154
{
155
    BLOCK_START("PlayerRecv::processPlayerStatUpdate2")
156
    const int type = msg.readInt16("type");
157
    const int value = msg.readInt32("value");
158
    playerHandler->setStat(msg, type, value, NoStat, Notify_true);
159
    BLOCK_END("PlayerRecv::processPlayerStatUpdate2")
160
}
161
162
void PlayerRecv::processPlayerStatUpdate3(Net::MessageIn &msg)
163
{
164
    BLOCK_START("PlayerRecv::processPlayerStatUpdate3")
165
    const int type = msg.readInt32("type");
166
    const int base = msg.readInt32("base");
167
    const int bonus = msg.readInt32("bonus");
168
169
    playerHandler->setStat(msg, type, base, bonus, Notify_false);
170
    BLOCK_END("PlayerRecv::processPlayerStatUpdate3")
171
}
172
173
void PlayerRecv::processPlayerStatUpdate4(Net::MessageIn &msg)
174
{
175
    BLOCK_START("PlayerRecv::processPlayerStatUpdate4")
176
    const uint16_t type = msg.readInt16("type");
177
    const uint8_t ok = msg.readUInt8("flag");
178
    const int value = msg.readUInt8("value");
179
180
    if (ok != 1)
181
    {
182
        const int oldValue = PlayerInfo::getStatBase(
183
            static_cast<AttributesT>(type));
184
        const int points = PlayerInfo::getAttribute(
185
            Attributes::PLAYER_CHAR_POINTS) + oldValue - value;
186
        PlayerInfo::setAttribute(Attributes::PLAYER_CHAR_POINTS, points);
187
        NotifyManager::notify(NotifyTypes::SKILL_RAISE_ERROR);
188
    }
189
190
    playerHandler->setStat(msg, type, value, NoStat, Notify_true);
191
    BLOCK_END("PlayerRecv::processPlayerStatUpdate4")
192
}
193
194
void PlayerRecv::processPlayerStatUpdate6(Net::MessageIn &msg)
195
{
196
    BLOCK_START("PlayerRecv::processPlayerStatUpdate6")
197
    const int type = msg.readInt16("type");
198
    const int value = msg.readUInt8("value");
199
    if (statusWindow != nullptr)
200
        playerHandler->setStat(msg, type, value, NoStat, Notify_true);
201
    BLOCK_END("PlayerRecv::processPlayerStatUpdate6")
202
}
203
204
void PlayerRecv::processPlayerArrowMessage(Net::MessageIn &msg)
205
{
206
    BLOCK_START("PlayerRecv::processPlayerArrowMessage")
207
    const int type = msg.readInt16("type");
208
    switch (type)
209
    {
210
        case 0:
211
            NotifyManager::notify(NotifyTypes::ARROWS_EQUIP_NEEDED);
212
            break;
213
        case 3:
214
            // arrows equiped
215
            break;
216
        default:
217
            UNIMPLEMENTEDPACKETFIELD(type);
218
            break;
219
    }
220
    BLOCK_END("PlayerRecv::processPlayerArrowMessage")
221
}
222
223
void PlayerRecv::processMapMusic(Net::MessageIn &msg)
224
{
225
    const int size = msg.readInt16("len") - 4;
226
    const std::string music = msg.readString(size, "name");
227
    soundManager.playMusic(music,
228
        SkipError_false);
229
230
    Map *const map = viewport->getMap();
231
    if (map != nullptr)
232
        map->setMusicFile(music);
233
}
234
235
void PlayerRecv::processMapMask(Net::MessageIn &msg)
236
{
237
    const int mask = msg.readInt32("mask");
238
    msg.readInt32("unused");
239
    Map *const map = Game::instance()->getCurrentMap();
240
    if (map != nullptr)
241
        map->setMask(mask);
242
}
243
244
void PlayerRecv::processPlayerClientCommand(Net::MessageIn &msg)
245
{
246
    const int sz = msg.readInt16("len") - 4;
247
    std::string command = msg.readString(sz, "command");
248
    std::string cmd;
249
    std::string args;
250
251
    if (settings.awayMode ||
252
        settings.pseudoAwayMode ||
253
        !settings.enableRemoteCommands)
254
    {
255
        return;
256
    }
257
258
    if (!parse2Str(command, cmd, args))
259
    {
260
        cmd = STD_MOVE(command);
261
        args.clear();
262
    }
263
    inputManager.executeRemoteChatCommand(cmd, args, nullptr);
264
}
265
266
4
}  // namespace Ea