diff options
Diffstat (limited to 'src/mumblemanager.cpp')
-rw-r--r-- | src/mumblemanager.cpp | 273 |
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)); +} |