summaryrefslogtreecommitdiff
path: root/src/mumblemanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mumblemanager.cpp')
-rw-r--r--src/mumblemanager.cpp273
1 files changed, 273 insertions, 0 deletions
diff --git a/src/mumblemanager.cpp b/src/mumblemanager.cpp
new file mode 100644
index 000000000..6586f9546
--- /dev/null
+++ b/src/mumblemanager.cpp
@@ -0,0 +1,273 @@
+/* Code taken from: http://mumble.sourceforge.net/Link */
+
+#include "mumblemanager.h"
+
+#include "configuration.h"
+#include "log.h"
+
+#include "utils/mathutils.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <SDL_syswm.h>
+
+#ifndef WIN32
+#include <sys/mman.h>
+#endif
+
+MumbleManager::MumbleManager() :
+ mLinkedMem(0)
+{
+ mMapBase[0] = mMapBase[1] = mMapBase[2] = 0.;
+ init();
+}
+
+MumbleManager::~MumbleManager()
+{
+ if (mLinkedMem)
+ {
+#ifdef WIN32
+ UnmapViewOfFile(mLinkedMem);
+#elif defined __FreeBSD__ || defined __DragonFly__
+#else
+ munmap(mLinkedMem, sizeof(struct LinkedMem));
+#endif
+ mLinkedMem = 0;
+ }
+}
+
+uint16_t MumbleManager::getMapId(std::string mapName)
+{
+ uint16_t res = 0;
+ if (mapName.size() != 5 || mapName[3] != '-')
+ {
+ res = getCrc16(mapName);
+ }
+ else
+ {
+ mapName = mapName.substr(0, 3) + mapName[4];
+ res = atoi(mapName.c_str());
+ }
+ return res;
+}
+
+void MumbleManager::setMapBase(uint16_t mapid)
+{
+ mMapBase[0] = 10000. * (mapid & 0x1f);
+ mapid >>= 5;
+ mMapBase[1] = 1000. * (mapid & 0x3f);
+ mapid >>= 6;
+ mMapBase[2] = 10000. * (mapid & 0x1f);
+}
+
+void MumbleManager::init()
+{
+#if defined __FreeBSD__ || defined __DragonFly__
+ return;
+#endif
+
+ if (mLinkedMem || !config.getBoolValue("enableMumble"))
+ return;
+
+ logger->log1("MumbleManager::init");
+#ifdef WIN32
+ HANDLE hMapObject = OpenFileMappingW(FILE_MAP_ALL_ACCESS,
+ FALSE, L"MumbleLink");
+ if (hMapObject == NULL)
+ {
+ logger->log1("MumbleManager::init cant open MumbleLink");
+ return;
+ }
+
+ mLinkedMem = (LinkedMem *) MapViewOfFile(hMapObject,
+ FILE_MAP_ALL_ACCESS, 0, 0, sizeof(LinkedMem));
+
+ if (mLinkedMem == NULL)
+ {
+ CloseHandle(hMapObject);
+ hMapObject = NULL;
+ logger->log1("MumbleManager::init cant map MumbleLink");
+ return;
+ }
+#elif defined __FreeBSD__ || defined __DragonFly__
+#else
+ char memName[256];
+ snprintf(memName, 256, "/MumbleLink.%d", getuid());
+
+ int shmfd = shm_open(memName, O_RDWR, S_IRUSR | S_IWUSR);
+
+ if (shmfd < 0)
+ {
+ logger->log1("MumbleManager::init cant open shared memory MumbleLink");
+ return;
+ }
+
+ mLinkedMem = (LinkedMem *)(mmap(NULL, sizeof(struct LinkedMem),
+ PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0));
+
+ if (mLinkedMem == (void *)(-1))
+ {
+ mLinkedMem = NULL;
+ logger->log1("MumbleManager::init cant map MumbleLink");
+ return;
+ }
+
+#endif
+ wcsncpy(mLinkedMemCache.name, L"Mana", 256);
+ wcsncpy(mLinkedMemCache.description, L"TheManaWorld Plugin", 2048);
+ mLinkedMemCache.uiVersion = 2;
+
+ // Left handed coordinate system.
+ // X positive towards "left".
+ // Y positive towards "up".
+ // Z positive towards "into screen".
+ //
+ // 1 unit = 1 meter
+
+ // Unit vector pointing out of the avatars eyes (here Front looks into scene).
+ /* no way to look "up", 2d */
+ mLinkedMemCache.fAvatarFront[1] = 0.0f;
+
+ // Unit vector pointing out of the top of the avatars head
+ // (here Top looks straight up).
+ /* no way to change this in tmw */
+ mLinkedMemCache.fAvatarTop[0] = 0.0f;
+ mLinkedMemCache.fAvatarTop[1] = 1.0f;
+ mLinkedMemCache.fAvatarTop[2] = 0.0f;
+
+ mLinkedMemCache.fCameraFront[0] = 0.0f;
+ mLinkedMemCache.fCameraFront[1] = 0.0f;
+ mLinkedMemCache.fCameraFront[2] = 1.0f;
+
+ mLinkedMemCache.fCameraTop[0] = 0.0f;
+ mLinkedMemCache.fCameraTop[1] = 1.0f;
+ mLinkedMemCache.fCameraTop[2] = 0.0f;
+
+ mLinkedMemCache.uiTick++;
+}
+
+void MumbleManager::setPlayer(const std::string &userName)
+{
+ if (!mLinkedMem)
+ return;
+
+ // Identifier which uniquely identifies a certain player in a context
+ // (e.g. the ingame Name).
+ mbstowcs(mLinkedMemCache.identity, userName.c_str(), 256);
+ mLinkedMemCache.uiTick ++;
+ memcpy(mLinkedMem, &mLinkedMemCache, sizeof(mLinkedMemCache));
+}
+
+void MumbleManager::setAction(int action)
+{
+ if (!mLinkedMem)
+ return;
+
+ switch(action)
+ {
+ case 0: /* STAND */
+ case 1: /* WALK */
+ case 2: /* ATTACK */
+ case 5: /* HURT */
+ mLinkedMemCache.fAvatarPosition[1] = 1.5f;
+ break;
+ case 3: /* SIT */
+ mLinkedMemCache.fAvatarPosition[1] = 1.0f;
+ break;
+ case 4: /* DEAD */
+ default:
+ mLinkedMemCache.fAvatarPosition[1] = 0.0f;
+ break;
+ }
+ mLinkedMemCache.fAvatarPosition[1] += mMapBase[1];
+ mLinkedMemCache.fCameraPosition[1] = mLinkedMemCache.fAvatarPosition[1];
+
+ mLinkedMemCache.uiTick++;
+ memcpy(mLinkedMem, &mLinkedMemCache, sizeof(mLinkedMemCache));
+}
+
+void MumbleManager::setPos(int tileX, int tileY, int direction)
+{
+ if (!mLinkedMem)
+ return;
+
+ // Position of the avatar (here standing slightly off the origin)
+ // lm->fAvatarPosition
+
+ /* tmw coordinates work exactly the other way round */
+ mLinkedMemCache.fAvatarPosition[0] = tileX + mMapBase[0];
+ mLinkedMemCache.fAvatarPosition[2] = tileY + mMapBase[2];
+
+ // Same as avatar but for the camera.
+ // lm->fCameraPosition, fCameraFront, fCameraTop
+
+ // Same as avatar but for the camera.
+ mLinkedMemCache.fCameraPosition[0] = mLinkedMemCache.fAvatarPosition[0];
+ mLinkedMemCache.fCameraPosition[2] = mLinkedMemCache.fAvatarPosition[2];
+
+ // Unit vector pointing out of the avatars eyes
+ // (here Front looks into scene).
+ switch(direction)
+ {
+ case 4: /* UP */
+ mLinkedMemCache.fAvatarFront[0] = 0.0f;
+ mLinkedMemCache.fAvatarFront[2] = 1.0f;
+ break;
+ case 1: /* DOWN */
+ mLinkedMemCache.fAvatarFront[0] = 0.0f;
+ mLinkedMemCache.fAvatarFront[2] = -1.0f;
+ break;
+ case 2: /* LEFT */
+ mLinkedMemCache.fAvatarFront[0] = 1.0f;
+ mLinkedMemCache.fAvatarFront[2] = 0.0f;
+ break;
+ case 8: /* RIGHT */
+ mLinkedMemCache.fAvatarFront[0] = -1.0f;
+ mLinkedMemCache.fAvatarFront[2] = 0.0f;
+ break;
+ default:
+ break;
+ }
+
+ mLinkedMemCache.uiTick ++;
+ memcpy(mLinkedMem, &mLinkedMemCache, sizeof(mLinkedMemCache));
+}
+
+void MumbleManager::setMap(const std::string &mapName)
+{
+ if (!mLinkedMem)
+ return;
+
+ // Context should be equal for players which should be able to hear each
+ // other positional and differ for those who shouldn't
+ // (e.g. it could contain the server+port and team)
+
+ setMapBase(getMapId(mapName));
+ setAction(0); /* update y coordinate */
+}
+
+void MumbleManager::setServer(const std::string &serverName)
+{
+ if (!mLinkedMem)
+ return;
+
+ unsigned size = serverName.size();
+ if (size > sizeof(mLinkedMemCache.context) - 1)
+ size = sizeof(mLinkedMemCache.context) - 1;
+
+ memset(mLinkedMemCache.context, 0, sizeof(mLinkedMemCache.context));
+ memcpy(mLinkedMemCache.context, serverName.c_str(), size);
+ mLinkedMemCache.context[size] = '\0';
+ mLinkedMemCache.context_len = size;
+ mLinkedMemCache.uiTick ++;
+ memcpy(mLinkedMem, &mLinkedMemCache, sizeof(mLinkedMemCache));
+}