GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/mumblemanager.cpp Lines: 0 102 0.0 %
Date: 2021-03-17 Branches: 0 50 0.0 %

Line Branch Exec Source
1
/*
2
 *  Code taken from: http://mumble.sourceforge.net/Link
3
 *
4
 *  All code listed below is in the public domain and can be used, shared or
5
 *  modified freely
6
 *
7
 *  Copyright (C) 2011-2019  The ManaPlus Developers
8
 *  Copyright (C) 2019-2021  Andrei Karas
9
 */
10
11
#ifdef USE_MUMBLE
12
13
#include "mumblemanager.h"
14
15
#include "configuration.h"
16
#include "logger.h"
17
18
#include "utils/mathutils.h"
19
20
#if defined(__NetBSD__) || defined(__OpenBSD__)
21
#include <sys/param.h>
22
#endif  // defined(__NetBSD__) || defined(__OpenBSD__)
23
#include <wchar.h>
24
#include <cctype>
25
26
#include <fcntl.h>
27
#include <unistd.h>
28
#include <sys/types.h>
29
30
PRAGMA48(GCC diagnostic push)
31
PRAGMA48(GCC diagnostic ignored "-Wshadow")
32
#include <SDL_syswm.h>
33
PRAGMA48(GCC diagnostic pop)
34
35
#ifndef WIN32
36
#include <sys/mman.h>
37
#endif  // WIN32
38
39
#include "debug.h"
40
41
#ifdef USE_MUMBLE
42
MumbleManager *mumbleManager = nullptr;
43
#endif  // USE_MUMBLE
44
45
MumbleManager::MumbleManager() :
46
    mLinkedMem(nullptr),
47
    mLinkedMemCache()
48
{
49
    mMapBase[0] = mMapBase[1] = mMapBase[2] = 0.;
50
    init();
51
}
52
53
MumbleManager::~MumbleManager()
54
{
55
    if (mLinkedMem)
56
    {
57
#ifdef WIN32
58
        UnmapViewOfFile(mLinkedMem);
59
#elif defined BSD4_4
60
#else  // WIN32
61
62
        munmap(mLinkedMem, sizeof(LinkedMem));
63
#endif  // WIN32
64
65
        mLinkedMem = nullptr;
66
    }
67
}
68
69
uint16_t MumbleManager::getMapId(std::string mapName)
70
{
71
    uint16_t res = 0;
72
    if (mapName.size() != 5 || mapName[3] != '-')
73
    {
74
        res = getCrc16(mapName);
75
    }
76
    else
77
    {
78
        mapName = mapName.substr(0, 3) + mapName[4];
79
        res = CAST_U16(atoi(mapName.c_str()));
80
    }
81
    return res;
82
}
83
84
void MumbleManager::setMapBase(uint16_t mapid)
85
{
86
    mMapBase[0] = 10000.0F * (mapid & 0x1F);
87
    mapid >>= 5;
88
    mMapBase[1] = 1000.0F * (mapid & 0x3F);
89
    mapid >>= 6;
90
    mMapBase[2] = 10000.0F * (mapid & 0x1F);
91
}
92
93
void MumbleManager::init()
94
{
95
#if defined BSD4_4
96
    return;
97
#endif  // defined BSD4_4
98
99
    if (mLinkedMem || !config.getBoolValue("enableMumble"))
100
        return;
101
102
    logger->log1("MumbleManager::init");
103
#ifdef WIN32
104
    HANDLE hMapObject = OpenFileMappingW(FILE_MAP_ALL_ACCESS,
105
                                         FALSE, L"MumbleLink");
106
    if (!hMapObject)
107
    {
108
        logger->log1("MumbleManager::init can't open MumbleLink");
109
        return;
110
    }
111
112
    mLinkedMem = reinterpret_cast<LinkedMem *>(MapViewOfFile(hMapObject,
113
        FILE_MAP_ALL_ACCESS, 0, 0, sizeof(LinkedMem)));
114
115
    if (!mLinkedMem)
116
    {
117
        CloseHandle(hMapObject);
118
        hMapObject = nullptr;
119
        logger->log1("MumbleManager::init can't map MumbleLink");
120
        return;
121
    }
122
#elif defined BSD4_4
123
#else  // WIN32
124
125
    char memName[256];
126
    snprintf(memName, sizeof(memName), "/MumbleLink.%u", getuid());
127
128
    const int shmfd = shm_open(memName, O_RDWR, S_IRUSR | S_IWUSR);
129
130
    if (shmfd < 0)
131
    {
132
        logger->log1("MumbleManager::init can't"
133
            " open shared memory MumbleLink");
134
        return;
135
    }
136
137
    mLinkedMem = static_cast<LinkedMem *>(mmap(nullptr,
138
        sizeof(LinkedMem), PROT_READ | PROT_WRITE,
139
        MAP_SHARED, shmfd, 0));
140
141
    if (mLinkedMem == reinterpret_cast<void *>(-1))
142
    {
143
        mLinkedMem = nullptr;
144
        logger->log1("MumbleManager::init can't map MumbleLink");
145
        return;
146
    }
147
148
#endif  // WIN32
149
150
    wcsncpy(mLinkedMemCache.name, L"ManaPlus", 256);
151
    wcsncpy(mLinkedMemCache.description, L"ManaPlus Plugin", 2048);
152
    mLinkedMemCache.uiVersion = 2;
153
154
    // Left handed coordinate system.
155
    // X positive towards "left".
156
    // Y positive towards "up".
157
    // Z positive towards "into screen".
158
    //
159
    // 1 unit = 1 meter
160
161
    // Unit vector pointing out of the avatars eyes
162
    // (here Front looks into scene).
163
    /* no way to look "up", 2d */
164
    mLinkedMemCache.fAvatarFront[1] = 0.0F;
165
166
    // Unit vector pointing out of the top of the avatars head
167
    // (here Top looks straight up).
168
    /* no way to change this in tmw */
169
    mLinkedMemCache.fAvatarTop[0] = 0.0F;
170
    mLinkedMemCache.fAvatarTop[1] = 1.0F;
171
    mLinkedMemCache.fAvatarTop[2] = 0.0F;
172
173
    mLinkedMemCache.fCameraFront[0] = 0.0F;
174
    mLinkedMemCache.fCameraFront[1] = 0.0F;
175
    mLinkedMemCache.fCameraFront[2] = 1.0F;
176
177
    mLinkedMemCache.fCameraTop[0] = 0.0F;
178
    mLinkedMemCache.fCameraTop[1] = 1.0F;
179
    mLinkedMemCache.fCameraTop[2] = 0.0F;
180
181
    mLinkedMemCache.uiTick++;
182
}
183
184
void MumbleManager::setPlayer(const std::string &userName)
185
{
186
    if (!mLinkedMem)
187
        return;
188
189
    // Identifier which uniquely identifies a certain player in a context
190
    // (e.g. the ingame Name).
191
    mbstowcs(mLinkedMemCache.identity, userName.c_str(), 256);
192
    mLinkedMemCache.uiTick ++;
193
PRAGMA8(GCC diagnostic push)
194
PRAGMA8(GCC diagnostic ignored "-Wclass-memaccess")
195
    memcpy(mLinkedMem, &mLinkedMemCache, sizeof(mLinkedMemCache));
196
PRAGMA8(GCC diagnostic pop)
197
}
198
199
void MumbleManager::setAction(const int action)
200
{
201
    if (!mLinkedMem)
202
        return;
203
204
    switch (action)
205
    {
206
        case 0: /* STAND */
207
        case 1: /* WALK */
208
        case 2: /* ATTACK */
209
        case 5: /* HURT */
210
            mLinkedMemCache.fAvatarPosition[1] = 1.5F;
211
            break;
212
        case 3: /* SIT */
213
            mLinkedMemCache.fAvatarPosition[1] = 1.0F;
214
            break;
215
        case 4: /* DEAD */
216
        default:
217
            mLinkedMemCache.fAvatarPosition[1] = 0.0F;
218
            break;
219
    }
220
    mLinkedMemCache.fAvatarPosition[1] += mMapBase[1];
221
    mLinkedMemCache.fCameraPosition[1] = mLinkedMemCache.fAvatarPosition[1];
222
223
    mLinkedMemCache.uiTick++;
224
PRAGMA8(GCC diagnostic push)
225
PRAGMA8(GCC diagnostic ignored "-Wclass-memaccess")
226
    memcpy(mLinkedMem, &mLinkedMemCache, sizeof(mLinkedMemCache));
227
PRAGMA8(GCC diagnostic pop)
228
}
229
230
void MumbleManager::setPos(const int tileX, const int tileY,
231
                           const int direction)
232
{
233
    if (!mLinkedMem)
234
        return;
235
236
    // Position of the avatar (here standing slightly off the origin)
237
    // lm->fAvatarPosition
238
239
    /* tmw coordinates work exactly the other way round */
240
    mLinkedMemCache.fAvatarPosition[0] = static_cast<float>(tileX)
241
        + mMapBase[0];
242
    mLinkedMemCache.fAvatarPosition[2] = static_cast<float>(tileY)
243
        + mMapBase[2];
244
245
    // Same as avatar but for the camera.
246
    // lm->fCameraPosition, fCameraFront, fCameraTop
247
248
    // Same as avatar but for the camera.
249
    mLinkedMemCache.fCameraPosition[0] = mLinkedMemCache.fAvatarPosition[0];
250
    mLinkedMemCache.fCameraPosition[2] = mLinkedMemCache.fAvatarPosition[2];
251
252
    // Unit vector pointing out of the avatars eyes
253
    // (here Front looks into scene).
254
    switch (direction)
255
    {
256
        case 4: /* UP */
257
            mLinkedMemCache.fAvatarFront[0] = 0.0F;
258
            mLinkedMemCache.fAvatarFront[2] = 1.0F;
259
            break;
260
        case 1: /* DOWN */
261
            mLinkedMemCache.fAvatarFront[0] = 0.0F;
262
            mLinkedMemCache.fAvatarFront[2] = -1.0F;
263
            break;
264
        case 2: /* LEFT */
265
            mLinkedMemCache.fAvatarFront[0] = 1.0F;
266
            mLinkedMemCache.fAvatarFront[2] = 0.0F;
267
            break;
268
        case 8: /* RIGHT */
269
            mLinkedMemCache.fAvatarFront[0] = -1.0F;
270
            mLinkedMemCache.fAvatarFront[2] = 0.0F;
271
            break;
272
        default:
273
            break;
274
    }
275
276
    mLinkedMemCache.uiTick ++;
277
PRAGMA8(GCC diagnostic push)
278
PRAGMA8(GCC diagnostic ignored "-Wclass-memaccess")
279
    memcpy(mLinkedMem, &mLinkedMemCache, sizeof(mLinkedMemCache));
280
PRAGMA8(GCC diagnostic pop)
281
}
282
283
void MumbleManager::setMap(const std::string &mapName)
284
{
285
    if (!mLinkedMem)
286
        return;
287
288
    // Context should be equal for players which should be able to hear each
289
    // other positional and differ for those who shouldn't
290
    // (e.g. it could contain the server+port and team)
291
292
    setMapBase(getMapId(mapName));
293
    setAction(0); /* update y coordinate */
294
}
295
296
void MumbleManager::setServer(const std::string &serverName)
297
{
298
    if (!mLinkedMem)
299
        return;
300
301
    unsigned size = CAST_U32(serverName.size());
302
    if (size > sizeof(mLinkedMemCache.context) - 1)
303
        size = sizeof(mLinkedMemCache.context) - 1;
304
305
    memset(mLinkedMemCache.context, 0, sizeof(mLinkedMemCache.context));
306
PRAGMA8(GCC diagnostic push)
307
PRAGMA8(GCC diagnostic ignored "-Wclass-memaccess")
308
    memcpy(mLinkedMemCache.context, serverName.c_str(), size);
309
PRAGMA8(GCC diagnostic pop)
310
    mLinkedMemCache.context[size] = '\0';
311
    mLinkedMemCache.context_len = size;
312
    mLinkedMemCache.uiTick ++;
313
PRAGMA8(GCC diagnostic push)
314
PRAGMA8(GCC diagnostic ignored "-Wclass-memaccess")
315
    memcpy(mLinkedMem, &mLinkedMemCache, sizeof(mLinkedMemCache));
316
PRAGMA8(GCC diagnostic pop)
317
}
318
319
#endif  // USE_MUMBLE