- attempt to fix network game play 'stuttering'

- bugfix for ip address gathering
- added tab autocomplete in chat windows for playernames
This commit is contained in:
Mark Vejvoda 2011-11-24 23:15:21 +00:00
parent 1935f9314b
commit c6b7d3991e
6 changed files with 166 additions and 32 deletions

View File

@ -112,7 +112,6 @@ void ChatManager::keyDown(SDL_KeyboardEvent key) {
}
}
//if(key==vkReturn) {
if(isKeyPressed(SDLK_RETURN,key, false) == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] key = [%c] [%d]\n",__FILE__,__FUNCTION__,__LINE__,key.keysym.sym,key.keysym.sym);
@ -158,7 +157,43 @@ void ChatManager::keyDown(SDL_KeyboardEvent key) {
}
}
}
//else if(key==vkBack) {
else if(isKeyPressed(SDLK_TAB,key, false) == true) {
// First find the prefix characters to auto-complete
string autoCompleteName = "";
if(text.empty() == false) {
int startPos = -1;
for(int i = text.size()-1; i >= 0; --i) {
if(text[i] != ' ') {
startPos = i;
}
else {
break;
}
}
if(startPos >= 0) {
autoCompleteName = text.substr(startPos);
// Now lookup the prefix for a match in playernames
string autoCompleteResult = "";
GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface();
const GameSettings *settings = gameNetworkInterface->getGameSettings();
for(unsigned int factionIndex = 0; factionIndex < settings->getFactionCount(); ++factionIndex) {
string playerName = settings->getNetworkPlayerName(factionIndex);
if(playerName.length() > autoCompleteName.length() &&
StartsWith(toLower(playerName), toLower(autoCompleteName)) == true) {
autoCompleteResult = playerName.substr(autoCompleteName.length());
break;
}
}
if(autoCompleteResult != "") {
WString addText(autoCompleteResult);
appendText(addText.cw_str(), false);
}
}
}
}
else if(isKeyPressed(SDLK_BACKSPACE,key,false) == true) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] key = [%c] [%d]\n",__FILE__,__FUNCTION__,__LINE__,key.keysym.sym,key.keysym.sym);
@ -195,6 +230,34 @@ void ChatManager::switchOnEdit() {
textCharLength.clear();
}
void ChatManager::appendText(const wchar_t *addText, bool validateChars) {
for(unsigned int i = 0; i < wcslen(addText); ++i) {
wchar_t key = addText[i];
if(validateChars == false || isAllowedInputTextKey(key)) {
char buf[4] = {0};
if (key < 0x80) {
buf[0] = key;
textCharLength.push_back(1);
//printf("1 char, textCharLength = %d\n",textCharLength.size());
}
else if (key < 0x800) {
buf[0] = (0xC0 | key >> 6);
buf[1] = (0x80 | key & 0x3F);
textCharLength.push_back(2);
//printf("2 char, textCharLength = %d\n",textCharLength.size());
}
else {
buf[0] = (0xE0 | key >> 12);
buf[1] = (0x80 | key >> 6 & 0x3F);
buf[2] = (0x80 | key & 0x3F);
textCharLength.push_back(3);
//printf("3 char, textCharLength = %d\n",textCharLength.size());
}
text += buf;
}
}
}
void ChatManager::keyPress(SDL_KeyboardEvent c) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] key = [%c] [%d]\n",__FILE__,__FUNCTION__,__LINE__,c.keysym.sym,c.keysym.sym);
@ -203,6 +266,11 @@ void ChatManager::keyPress(SDL_KeyboardEvent c) {
//space is the first meaningful code
// SDLKey key = extractKeyPressed(c);
// if(isAllowedInputTextKey(key)) {
wchar_t key = extractKeyPressedUnicode(c);
wchar_t textAppend[] = { key, 0 };
appendText(textAppend);
/*
wchar_t key = extractKeyPressedUnicode(c);
if(isAllowedInputTextKey(key)) {
//char szCharText[20]="";
@ -238,6 +306,7 @@ void ChatManager::keyPress(SDL_KeyboardEvent c) {
//delete [] utfStr;
}
*/
}
}

View File

@ -50,6 +50,8 @@ private:
Font3D *font3D;
void appendText(const wchar_t *addText, bool validateChars=true);
public:
ChatManager();
void init(Console* console, int thisTeamIndex, const bool inMenu=false, string manualPlayerNameOverride="");

View File

@ -311,9 +311,9 @@ void ConnectionSlot::updateSlot(ConnectionSlotEvent *event) {
//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] MUTEX LOCK held for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
// This means no clients are trying to connect at the moment
if(this->getSocket() == NULL) {
checkForNewClients = false;
}
//if(this->getSocket() == NULL) {
// checkForNewClients = false;
//}
}
//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] MUTEX LOCK held for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
}
@ -416,7 +416,7 @@ void ConnectionSlot::update(bool checkForNewClients,int lockedSlotIndex) {
//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
//send intro message when connected
if(this->getSocket() != NULL) {
if(this->isConnected() == true) {
//RandomGen random;
//sessionKey = random.randRange(-100000, 100000);
srand(time(NULL) / (this->playerIndex + 1));
@ -427,10 +427,10 @@ void ConnectionSlot::update(bool checkForNewClients,int lockedSlotIndex) {
if(hasOpenSlots == false) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] !!!!!!!!WARNING - no open slots, disconnecting client\n",__FILE__,__FUNCTION__,__LINE__);
if(this->getSocket() != NULL) {
//if(this->getSocket() != NULL) {
NetworkMessageIntro networkMessageIntro(sessionKey,getNetworkVersionSVNString(), getHostName(), playerIndex, nmgstNoSlots, 0, ServerSocket::getFTPServerPort(),"");
sendMessage(&networkMessageIntro);
}
//}
//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
@ -439,12 +439,12 @@ void ConnectionSlot::update(bool checkForNewClients,int lockedSlotIndex) {
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] client will be assigned to the next open slot\n",__FILE__,__FUNCTION__,__LINE__);
if(this->getSocket() != NULL) {
//if(this->getSocket() != NULL) {
NetworkMessageIntro networkMessageIntro(sessionKey,getNetworkVersionSVNString(), getHostName(), playerIndex, nmgstOk, 0, ServerSocket::getFTPServerPort(),"");
sendMessage(&networkMessageIntro);
//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
}
//}
}
}
}
@ -455,14 +455,14 @@ void ConnectionSlot::update(bool checkForNewClients,int lockedSlotIndex) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
if(this->getSocket() != NULL && this->getSocket()->isConnected()) {
if(this->isConnected()) {
//if(chrono.getMillis() > 1) printf("In [%s::%s Line: %d] action running for msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,(long long int)chrono.getMillis());
this->clearChatInfo();
bool gotTextMsg = true;
for(;this->getSocket() != NULL && this->getSocket()->hasDataToRead() == true && gotTextMsg == true;) {
for(;this->hasDataToRead() == true && gotTextMsg == true;) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] polling for networkMessageType...\n",__FILE__,__FUNCTION__,__LINE__);
NetworkMessageType networkMessageType= getNextMessageType(true);
@ -1041,8 +1041,15 @@ void ConnectionSlot::close() {
}
bool ConnectionSlot::hasValidSocketId() {
bool result = (this->getSocket() != NULL && this->getSocket()->getSocketId() > 0);
return result;
//bool result = (this->getSocket() != NULL && this->getSocket()->getSocketId() > 0);
//return result;
bool result = false;
MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE);
if(socket != NULL && socket->getSocketId() > 0) {
result = true;
}
return result;
}
Mutex * ConnectionSlot::getServerSynchAccessor() {
@ -1117,6 +1124,15 @@ bool ConnectionSlot::isConnected() {
return result;
}
PLATFORM_SOCKET ConnectionSlot::getSocketId() {
PLATFORM_SOCKET result = 0;
MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE);
if(socket != NULL) {
result = socket->getSocketId();
}
return result;
}
Socket* ConnectionSlot::getSocket() {
MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE);
return socket;
@ -1133,4 +1149,14 @@ void ConnectionSlot::deleteSocket() {
socket = NULL;
}
bool ConnectionSlot::hasDataToRead() {
bool result = false;
MutexSafeWrapper safeMutexSlot(&mutexSocket,CODE_AT_LINE);
if(socket != NULL && socket->hasDataToRead() == true) {
result = true;
}
return result;
}
}}//end namespace

View File

@ -192,6 +192,8 @@ public:
void updateSlot(ConnectionSlotEvent *event);
virtual bool isConnected();
PLATFORM_SOCKET getSocketId();
protected:
Mutex * getServerSynchAccessor();
@ -201,6 +203,8 @@ protected:
void setSocket(Socket *newSocket);
void deleteSocket();
virtual void update() {}
bool hasDataToRead();
};
}}//end namespace

View File

@ -648,9 +648,11 @@ void ServerInterface::updateSocketTriggeredList(std::map<PLATFORM_SOCKET,bool> &
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],CODE_AT_LINE_X(i));
ConnectionSlot* connectionSlot= slots[i];
if(connectionSlot != NULL && connectionSlot->getSocket() != NULL &&
connectionSlot->getSocket()->isSocketValid() == true) {
socketTriggeredList[connectionSlot->getSocket()->getSocketId()] = false;
if(connectionSlot != NULL) {
PLATFORM_SOCKET clientSocket = connectionSlot->getSocketId();
if(Socket::isSocketValid(&clientSocket) == true) {
socketTriggeredList[clientSocket] = false;
}
}
}
}
@ -659,7 +661,6 @@ void ServerInterface::validateConnectedClients() {
for(int i= 0; exitServer == false && i < GameConstants::maxPlayers; ++i) {
MutexSafeWrapper safeMutexSlot(&slotAccessorMutexes[i],CODE_AT_LINE_X(i));
ConnectionSlot* connectionSlot = slots[i];
if(connectionSlot != NULL) {
connectionSlot->validateConnection();
}
@ -675,8 +676,12 @@ void ServerInterface::signalClientsToRecieveData(std::map<PLATFORM_SOCKET,bool>
ConnectionSlot* connectionSlot = slots[i];
bool socketTriggered = false;
if(connectionSlot != NULL && connectionSlot->getSocket() != NULL) {
socketTriggered = socketTriggeredList[connectionSlot->getSocket()->getSocketId()];
if(connectionSlot != NULL) {
PLATFORM_SOCKET clientSocket = connectionSlot->getSocketId();
if(Socket::isSocketValid(&clientSocket)) {
socketTriggered = socketTriggeredList[clientSocket];
}
}
ConnectionSlotEvent &event = eventList[i];
mapSlotSignalledList[i] = signalClientReceiveCommands(connectionSlot,i,socketTriggered,event);
@ -806,8 +811,9 @@ void ServerInterface::checForLaggingClients(std::map<int,bool> &mapSlotSignalled
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d, clientLagExceededOrWarned.first = %d, clientLagExceededOrWarned.second = %d\n",__FILE__,__FUNCTION__,__LINE__,clientLagExceededOrWarned.first,clientLagExceededOrWarned.second);
bool socketTriggered = false;
if(connectionSlot->getSocket() != NULL && connectionSlot->getSocket()->getSocketId() > 0) {
socketTriggered = socketTriggeredList[connectionSlot->getSocket()->getSocketId()];
PLATFORM_SOCKET clientSocket = connectionSlot->getSocketId();
if(clientSocket > 0) {
socketTriggered = socketTriggeredList[clientSocket];
}
ConnectionSlotEvent &event = eventList[i];
mapSlotSignalledList[i] = signalClientReceiveCommands(connectionSlot,i,socketTriggered,event);

View File

@ -313,9 +313,27 @@ string Ip::getString() const{
# include <ifaddrs.h>
#endif
static uint32 SockAddrToUint32(struct sockaddr * a)
{
return ((a)&&(a->sa_family == AF_INET)) ? ntohl(((struct sockaddr_in *)a)->sin_addr.s_addr) : 0;
static uint32 SockAddrToUint32(struct in_addr * a) {
uint32 result = 0;
//printf("a [%p]\n",a);
if(a != NULL) {
result = ntohl(a->s_addr);
}
return result;
}
static uint32 SockAddrToUint32(struct sockaddr * a) {
uint32 result = 0;
//printf("a [%p] family = %d\n",a,(a ? a->sa_family : -1));
if(a != NULL && (a->sa_family == AF_INET || a->sa_family == AF_UNSPEC)) {
//result = SockAddrToUint32((((struct sockaddr_in *)a)->sin_addr.s_addr);
result = SockAddrToUint32(&((struct sockaddr_in *)a)->sin_addr);
}
return result;
}
// convert a numeric IP address into its string representation
@ -651,12 +669,17 @@ std::vector<std::string> Socket::getLocalIPAddressList() {
if(myhostent) {
// get all host IP addresses (Except for loopback)
char myhostaddr[101] = "";
int ipIdx = 0;
while (myhostent->h_addr_list[ipIdx] != 0) {
//int ipIdx = 0;
//while (myhostent->h_addr_list[ipIdx] != 0) {
for(int ipIdx = 0; myhostent->h_addr_list[ipIdx] != NULL; ++ipIdx) {
//sprintf(myhostaddr, "%s",inet_ntoa(*(struct in_addr *)myhostent->h_addr_list[ipIdx]));
Inet_NtoA(SockAddrToUint32((struct sockaddr *)&myhostent->h_addr_list[ipIdx]), myhostaddr);
//struct sockaddr_in SockAddr;
//memcpy(&(SockAddr.sin_addr),&myhostent->h_addr[ipIdx],myhostent->h_length);
//SockAddr.sin_family = myhostent->h_addrtype;
//Inet_NtoA(SockAddrToUint32((sockaddr *)&SockAddr), myhostaddr);
Inet_NtoA(SockAddrToUint32((struct in_addr *)myhostent->h_addr_list[ipIdx]), myhostaddr);
//printf("%s\n",myhostaddr);
//printf("ipIdx = %d [%s]\n",ipIdx,myhostaddr);
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] myhostaddr = [%s]\n",__FILE__,__FUNCTION__,__LINE__,myhostaddr);
if(strlen(myhostaddr) > 0 &&
@ -664,7 +687,7 @@ std::vector<std::string> Socket::getLocalIPAddressList() {
strncmp(myhostaddr,"0.",2) != 0) {
ipList.push_back(myhostaddr);
}
ipIdx++;
//ipIdx++;
}
}
@ -710,7 +733,7 @@ std::vector<std::string> Socket::getLocalIPAddressList() {
struct sockaddr_in *pSockAddr = (struct sockaddr_in *)&ifr.ifr_addr;
if(pSockAddr != NULL) {
//sprintf(myhostaddr, "%s",inet_ntoa(pSockAddr->sin_addr));
Inet_NtoA(SockAddrToUint32((struct sockaddr *)&pSockAddr->sin_addr), myhostaddr);
Inet_NtoA(SockAddrToUint32(&pSockAddr->sin_addr), myhostaddr);
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] szBuf [%s], myhostaddr = [%s], ifr.ifr_flags = %d, ifrA.ifr_flags = %d, ifr.ifr_name [%s]\n",__FILE__,__FUNCTION__,__LINE__,szBuf,myhostaddr,ifr.ifr_flags,ifrA.ifr_flags,ifr.ifr_name);
// Now only include interfaces that are both UP and running
@ -1794,7 +1817,9 @@ void BroadCastClientSocketThread::execute() {
else {
//string fromIP = inet_ntoa(bcSender.sin_addr);
char szHostFrom[100]="";
Inet_NtoA(SockAddrToUint32((struct sockaddr *)&bcSender.sin_addr), szHostFrom);
Inet_NtoA(SockAddrToUint32(&bcSender.sin_addr), szHostFrom);
//printf("Client szHostFrom [%s]\n",szHostFrom);
string fromIP = szHostFrom;
if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"broadcast message received: [%s] from: [%s]\n", buff,fromIP.c_str() );
@ -2500,6 +2525,8 @@ void BroadCastSocketThread::execute() {
std::vector<std::string> ipSubnetMaskList;
for(unsigned int idx = 0; idx < ipList.size() && idx < MAX_NIC_COUNT; idx++) {
string broadCastAddress = getNetworkInterfaceBroadcastAddress(ipList[idx]);
//printf("idx = %d broadCastAddress [%s]\n",idx,broadCastAddress.c_str());
//strcpy(subnetmask[idx], broadCastAddress.c_str());
if(broadCastAddress != "" && std::find(ipSubnetMaskList.begin(),ipSubnetMaskList.end(),broadCastAddress) == ipSubnetMaskList.end()) {
ipSubnetMaskList.push_back(broadCastAddress);