Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable unicode characters for TS channel and Arma server names #996

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions extensions/src/ACRE2Core/setTs3ChannelDetails.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@
#include "Log.h"
#include "TextMessage.h"
#include "Engine.h"
#include "StringConversions.h"
#include "String"

#include <sstream>

RPC_FUNCTION(setTs3ChannelDetails) {
const std::vector<std::string> details = {
std::string((char *)vMessage->getParameter(0)),
std::string((char *)vMessage->getParameter(1)),
std::string((char *)vMessage->getParameter(2))
const std::vector<std::wstring> details = {
StringConversions::stringToWstring(std::string((char *)vMessage->getParameter(0))),
StringConversions::stringToWstring(std::string((char *)vMessage->getParameter(1))),
StringConversions::stringToWstring(std::string((char *)vMessage->getParameter(2)))
};

CEngine::getInstance()->getClient()->updateTs3ChannelDetails(details);
Expand All @@ -24,3 +26,5 @@ RPC_FUNCTION(setTs3ChannelDetails) {
protected:
char* m_Name;
};


61 changes: 31 additions & 30 deletions extensions/src/ACRE2DistortionTestPlugin/TS3Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "shlobj.h"
#include "Shlwapi.h"
#include "Log.h"
#include <StringConversions.h>
#include <thread>
#include <exception>
#include <sstream>
Expand All @@ -19,7 +20,7 @@
#pragma comment(lib, "Shlwapi.lib")

#define INVALID_TS3_CHANNEL -1
#define DEFAULT_TS3_CHANNEL "ACRE"
#define DEFAULT_TS3_CHANNEL L"ACRE"

extern TS3Functions ts3Functions;

Expand Down Expand Up @@ -458,7 +459,7 @@ acre::Result CTS3Client::unMuteAll( void ) {
acre::Result CTS3Client::moveToServerTS3Channel() {
if (!CAcreSettings::getInstance()->getDisableTS3ChannelSwitch()) {
anyID clientId;
std::vector<std::string> details = getTs3ChannelDetails();
std::vector<std::wstring> details = getTs3ChannelDetails();

if (ts3Functions.getClientID(ts3Functions.getCurrentServerConnectionHandlerID(), &clientId) == ERROR_ok) {
uint64_t currentChannelId = INVALID_TS3_CHANNEL;
Expand All @@ -468,11 +469,11 @@ acre::Result CTS3Client::moveToServerTS3Channel() {

const uint64_t channelId = findChannelByNames(details);
if ((channelId != INVALID_TS3_CHANNEL) && (channelId != currentChannelId)) {
std::string password = "";
if (details.at(1) != "" && details.at(0) != "") {
std::wstring password = L"";
if (details.at(1) != L"" && details.at(0) != L"") {
password = details.at(1);
}
ts3Functions.requestClientMove(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, password.c_str(), nullptr);
ts3Functions.requestClientMove(ts3Functions.getCurrentServerConnectionHandlerID(), clientId, channelId, StringConversions::wStringToString(password).c_str(), nullptr);
}
}
}
Expand All @@ -497,23 +498,23 @@ acre::Result CTS3Client::moveToPreviousTS3Channel() {
return acre::Result::ok;
}

uint64_t CTS3Client::findChannelByNames(std::vector<std::string> details_) {
uint64_t *channelList;
uint64_t CTS3Client::findChannelByNames(std::vector<std::wstring> details_) {
uint64_t* channelList;
if (ts3Functions.getChannelList(ts3Functions.getCurrentServerConnectionHandlerID(), &channelList) == ERROR_ok) {
uint64_t channelId = INVALID_TS3_CHANNEL;
uint64_t defaultChannelId = INVALID_TS3_CHANNEL;
std::map<uint64, std::string> channelMap;
std::string name = details_.at(2);
if (details_.at(0) != "") {
std::map<uint64, std::wstring> channelMap;
std::wstring name = details_.at(2);
if (details_.at(0) != L"") {
name = details_.at(0);
}
while (*channelList) {
channelId = *channelList;
channelList++;
char* channelName;
if (ts3Functions.getChannelVariableAsString(ts3Functions.getCurrentServerConnectionHandlerID(), channelId, CHANNEL_NAME, &channelName) == ERROR_ok) {
std::string channelNameString = std::string(channelName);
if (channelNameString.find(DEFAULT_TS3_CHANNEL) != -1 || (details_.at(0) != "" && channelNameString == name)) {
std::wstring channelNameString = StringConversions::stringToWstring(std::string(channelName));
if (channelNameString.find(DEFAULT_TS3_CHANNEL) != -1 || (details_.at(0) != L"" && channelNameString == name)) {
if (channelNameString == DEFAULT_TS3_CHANNEL) {
defaultChannelId = channelId;
}
Expand All @@ -526,13 +527,13 @@ uint64_t CTS3Client::findChannelByNames(std::vector<std::string> details_) {
int32_t bestMatches = 0;
int32_t bestDistance = 10;
for (auto& element : channelMap) {
std::string fullChannelName = element.second;
std::wstring fullChannelName = element.second;
// Full comparison
if (fullChannelName.compare(name) == 0) {
bestChannelId = element.first;
break;
}
const std::string cleanChannelName = removeSubstrings(fullChannelName, DEFAULT_TS3_CHANNEL);
const std::wstring cleanChannelName = removeSubstrings(fullChannelName, DEFAULT_TS3_CHANNEL);
// Word comparison
const int32_t matches = getWordMatches(cleanChannelName, name);
if (matches > bestMatches) {
Expand All @@ -548,10 +549,11 @@ uint64_t CTS3Client::findChannelByNames(std::vector<std::string> details_) {
}
}
if (bestChannelId == INVALID_TS3_CHANNEL) {
if (details_.at(0) != "") {
details_.at(0) = "";
if (details_.at(0) != L"") {
details_.at(0) = L"";
bestChannelId = findChannelByNames(details_);
} else if (defaultChannelId != INVALID_TS3_CHANNEL) {
}
else if (defaultChannelId != INVALID_TS3_CHANNEL) {
bestChannelId = defaultChannelId;
}
}
Expand All @@ -560,14 +562,14 @@ uint64_t CTS3Client::findChannelByNames(std::vector<std::string> details_) {
return INVALID_TS3_CHANNEL;
}

unsigned int CTS3Client::getWordMatches(const std::string& string1_, const std::string& string2_) {
std::vector<std::string> words1, words2;
std::string temp;
std::stringstream stringstream1(string1_);
unsigned int CTS3Client::getWordMatches(const std::wstring& string1_, const std::wstring& string2_) {
std::vector<std::wstring> words1, words2;
std::wstring temp;
std::wstringstream stringstream1(string1_);
while (stringstream1 >> temp) {
words1.push_back(temp);
}
std::stringstream stringstream2(string2_);
std::wstringstream stringstream2(string2_);
while (stringstream2 >> temp) {
words2.push_back(temp);
}
Expand All @@ -583,13 +585,13 @@ unsigned int CTS3Client::getWordMatches(const std::string& string1_, const std::
return matches;
}

uint32_t CTS3Client::levenshteinDistance(const std::string& string1_, const std::string& string2_) {
uint32_t CTS3Client::levenshteinDistance(const std::wstring& string1_, const std::wstring& string2_) {
int32_t length1 = string1_.size();
const int32_t length2 = string2_.size();

const decltype(length1) columnStart = decltype(length1)(1);

decltype(length1)*const column = new decltype(length1)[length1 + 1];
decltype(length1)* const column = new decltype(length1)[length1 + 1];
std::iota(column + columnStart, column + length1 + 1, columnStart);

for (auto x = columnStart; x <= length2; x++) {
Expand All @@ -611,16 +613,15 @@ uint32_t CTS3Client::levenshteinDistance(const std::string& string1_, const std:
return result;
}

std::string CTS3Client::removeSubstrings(std::string string_, std::string substring_) {
const std::string::size_type substringLength = substring_.length();
for (auto iterator = string_.find(substring_);
iterator != std::string::npos;
iterator = string_.find(substring_))
std::wstring CTS3Client::removeSubstrings(std::wstring string_, std::wstring substring_) {
const std::wstring::size_type substringLength = substring_.length();
for (auto iterator = string_.find(substring_); iterator != std::wstring::npos; iterator = string_.find(substring_)) {
string_.erase(iterator, substringLength);
}
return string_;
}

acre::Result CTS3Client::updateTs3ChannelDetails(std::vector<std::string> details_) {
acre::Result CTS3Client::updateTs3ChannelDetails(std::vector<std::wstring> details_) {
setTs3ChannelDetails(details_);
if (!details_.empty()) {
updateShouldSwitchTS3Channel(true);
Expand Down
12 changes: 6 additions & 6 deletions extensions/src/ACRE2DistortionTestPlugin/TS3Client.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,11 @@ class CTS3Client : public IClient {

acre::Result moveToServerTS3Channel();
acre::Result moveToPreviousTS3Channel();
uint64 findChannelByNames(std::vector<std::string> details_);
uint32_t getWordMatches(const std::string& string1_, const std::string& string2_);
uint32_t levenshteinDistance(const std::string& string1_, const std::string& string2_);
std::string removeSubstrings(std::string string_, std::string substring_);
acre::Result updateTs3ChannelDetails(std::vector<std::string> details_);
uint64 findChannelByNames(std::vector<std::wstring> details_);
uint32_t getWordMatches(const std::wstring& string1_, const std::wstring& string2_);
uint32_t levenshteinDistance(const std::wstring& string1_, const std::wstring& string2_);
std::wstring removeSubstrings(std::wstring string_, std::wstring substring_);
acre::Result updateTs3ChannelDetails(std::vector<std::wstring> details_);
acre::Result updateShouldSwitchTS3Channel(const bool state_);
bool shouldSwitchTS3Channel();

Expand All @@ -96,7 +96,7 @@ class CTS3Client : public IClient {
DECLARE_MEMBER(bool, IsX3DInitialized);
DECLARE_MEMBER(uint32_t, SpeakerMask);
DECLARE_MEMBER(uint64, PreviousTSChannel);
DECLARE_MEMBER(std::vector<std::string>, Ts3ChannelDetails);
DECLARE_MEMBER(std::vector<std::wstring>, Ts3ChannelDetails);
DECLARE_MEMBER(bool, ShouldSwitchTS3Channel)
protected:
std::thread m_versionThreadHandle;
Expand Down
2 changes: 1 addition & 1 deletion extensions/src/ACRE2Shared/IClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class IClient {

virtual acre::Result moveToServerTS3Channel() = 0;
virtual acre::Result moveToPreviousTS3Channel() = 0;
virtual acre::Result updateTs3ChannelDetails(const std::vector<std::string> details) = 0;
virtual acre::Result updateTs3ChannelDetails(const std::vector<std::wstring> details) = 0;
virtual acre::Result updateShouldSwitchTS3Channel(const bool state) = 0;
virtual bool shouldSwitchTS3Channel() = 0;

Expand Down
24 changes: 24 additions & 0 deletions extensions/src/ACRE2Shared/StringConversions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include "compat.h"

#include "StringConversions.h"
#include <string>

std::wstring StringConversions::stringToWstring(const std::string& str) {
const int32_t num_chars = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), nullptr, 0);
std::wstring wstrTo;
if (num_chars) {
wstrTo.resize(num_chars);
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &wstrTo[0], num_chars);
}
return wstrTo;
}

std::string StringConversions::wStringToString(const std::wstring& wstr) {
const int32_t num_chars = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), nullptr, 0, nullptr, nullptr);
std::string strTo;
if (num_chars > 0) {
strTo.resize(num_chars);
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), &strTo[0], num_chars, nullptr, nullptr);
}
return strTo;
}
9 changes: 9 additions & 0 deletions extensions/src/ACRE2Shared/StringConversions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <string>

class StringConversions {
public:
static std::wstring stringToWstring(const std::string& str);
static std::string wStringToString(const std::wstring& wstr);
};
22 changes: 13 additions & 9 deletions extensions/src/ACRE2Shared/TextMessage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,19 @@ acre::Result CTextMessage::parse(char *const value, const size_t len) {
return acre::Result::ok;
}

// Check to make sure the entire chunk of data is a NULL terminated ascii string
for (size_t x = 0 ; x < len; x++) {
if (!__isascii(value[x]) && value[x] != 0x00) {
this->m_IsValid = false;
LOG("INVALID PACKET DETECTED l:%d", len);
return acre::Result::error;
}
if (value[x] == 0x00) { // null terminate, bail
break;
// Don't check for ascii only characters for setTs3ChannelDetails procedure
std::string text(value);
if (text.find("setTs3ChannelDetails") == std::string::npos) {
// Check to make sure the entire chunk of data is a NULL terminated ascii string
for (size_t x = 0U; x < len; x++) {
if (!__isascii(value[x]) && value[x] != 0x00) {
this->m_IsValid = false;
LOG("INVALID PACKET DETECTED l:%d", len);
return acre::Result::error;
}
if (value[x] == 0x00) { // null terminate, bail
break;
}
}
}

Expand Down
Loading