ManaPlus
mumblemanager.cpp
Go to the documentation of this file.
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 
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
#define CAST_U16
Definition: cast.h:29
#define CAST_U32
Definition: cast.h:31
bool getBoolValue(const std::string &key) const
void log1(const char *const log_text)
Definition: logger.cpp:238
Configuration config
#define PRAGMA8(str)
Definition: localconsts.h:211
#define PRAGMA48(str)
Definition: localconsts.h:199
#define nullptr
Definition: localconsts.h:45
Logger * logger
Definition: logger.cpp:89
uint16_t getCrc16(const std::string &str)
Definition: mathutils.h:186
int size()
Definition: emotedb.cpp:306
void init()
Definition: playerinfo.cpp:434