So I got some problems.
I’m trying to make an IRC client in UE4, but whenever I play it in standalone it just crashes. It works great in PIE, though.
I’ve made a custom C++ GameMode:
#pragma once
#include "CoreMinimal.h"
#include "Networking.h"
#include "GameFramework/GameModeBase.h"
#include "GM_FullMetalHunters.generated.h"
/**
*
*/
UCLASS()
class FULLMETALHUNTERS_API AGM_FullMetalHunters : public AGameModeBase
{
GENERATED_BODY()
protected:
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, meta = (DisplayName = "OnReceivedIrcData"), Category = "IRCChat")
void onReceivedData(const FString& data);
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, meta = (DisplayName = "OnIrcConnected"), Category = "IRCChat")
void onIRCConnected();
public:
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Connect to IRC Server"), Category = "IRCChat")
void ConnectToServer(FString server, int32 port, FString user, bool showIRCLog);
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Join Channel"), Category = "IRCChat")
void JoinChannel(FString channel);
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Send Command"), Category = "IRCChat")
bool SendCommand(FString command);
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Send Message"), Category = "IRCChat")
void SendMessage(FString channel, FString message);
UFUNCTION(BlueprintCallable, meta = (DisplayName = "Disconnect from Server"), Category = "IRCChat")
void Disconnect();
private:
FSocket* ListenerSocket;
FSocket* ConnectionSocket;
FTimerHandle timerHandle;
FString userName;
FString serverName;
//int32 portNum;
bool IRCLog;
void SocketListener();
void SendLogin(FString server, int32 portNumber);
//bool SendString(FString msg);
void ParseMessage(FString msg);
void ReceivedChatMessage(FString UserName, FString message);
};
and
#include "FullMetalHunters.h"
#include "GM_FullMetalHunters.h"
#include <string>
void AGM_FullMetalHunters::ConnectToServer(FString server, int32 port, FString user, bool showIRCLog)
{
userName = user;
showIRCLog = IRCLog;
FIPv4Endpoint Endpoint(FIPv4Address(127, 0, 0, 1), 6667);
FSocket* ListenerSocket = FTcpSocketBuilder(TEXT("TwitchListener"))
.AsReusable()
.BoundToEndpoint(Endpoint)
.Listening(8);
//Set Buffer Size
int32 NewSize = 0;
ListenerSocket->SetReceiveBufferSize(2 * 1024 * 1024, NewSize);
GetWorldTimerManager().SetTimer(timerHandle, this, &AGM_FullMetalHunters::SocketListener, 0.01, true);
SendLogin(server, port);
SendCommand(TEXT("NICK " + user));
SendCommand(TEXT("USER " + user + " 0 * :" + user));
}
void AGM_FullMetalHunters::SocketListener()
{
TArray<uint8> ReceivedData;
uint32 Size;
bool Received = false;
while (ListenerSocket->HasPendingData(Size))
{
Received = true;
ReceivedData.SetNumUninitialized(FMath::Min(Size, 65507u));
int32 Read = 0;
ListenerSocket->Recv(ReceivedData.GetData(), ReceivedData.Num(), Read);
}
if (Received)
{
const std::string cstr(reinterpret_cast<const char*>(ReceivedData.GetData()), ReceivedData.Num());
FString fs(cstr.c_str());
ParseMessage(fs);
}
}
void AGM_FullMetalHunters::ParseMessage(FString msg)
{
TArray<FString> lines;
msg.ParseIntoArrayLines(lines);
for (FString fs : lines)
{
TArray<FString> parts;
fs.ParseIntoArray(parts, TEXT(":"));
TArray<FString> meta;
parts[0].ParseIntoArrayWS(meta);
if (parts.Num() >= 2)
{
if (meta[0] == TEXT("PING"))
{
FString response = "PONG " + parts[1];
FTimerHandle timer;
GetWorldTimerManager().SetTimer(timer, [=]() {
SendCommand(*response);
//SendCommand(TEXT("JOIN " + channelNames[i]));
}, 1, false);
}
else if (meta.Num() == 3 && meta[1] == TEXT("PRIVMSG"))
{
FString message = parts[1];
if (parts.Num() > 2)
{
for (int i = 2; i < parts.Num(); i++)
{
message += TEXT(":") + parts[i];
}
}
FString username;
FString tmp;
meta[0].Split(TEXT("!"), &username, &tmp);
ReceivedChatMessage(username, message);
continue;
}
}
UE_LOG(LogTemp, Warning, TEXT("%s"), *fs);
// This is only for debugging purposes, it outputs the entire connection process (not good)
if (IRCLog)
this->onReceivedData(*fs);
}
}
void AGM_FullMetalHunters::ReceivedChatMessage(FString UserName, FString message)
{
//UE_LOG(LogTemp, Warning, TEXT("%s: %s"), *UserName, *message);
FString concatenatedMessage = UserName + ": " + message;
this->onReceivedData(*concatenatedMessage);
}
void AGM_FullMetalHunters::SendLogin(FString server, int32 portNumber)
{
auto ResolveInfo = ISocketSubsystem::Get()->GetHostByName(TCHAR_TO_ANSI(*server));
while (!ResolveInfo->IsComplete());
if (ResolveInfo->GetErrorCode() != 0)
{
//UE_LOG(LogTemp, Warning, TEXT("Couldn't resolve hostname."));
return;
}
const FInternetAddr* Addr = &ResolveInfo->GetResolvedAddress();
uint32 OutIP = 0;
Addr->GetIp(OutIP);
int32 port = portNumber;
TSharedRef<FInternetAddr> addr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
addr->SetIp(OutIP);
addr->SetPort(port);
ListenerSocket = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(NAME_Stream, TEXT("default"), false);
bool connected = ListenerSocket->Connect(*addr);
if (!connected)
{
//UE_LOG(LogTemp, Warning, TEXT("Failed to connect."));
if (ListenerSocket)
ListenerSocket->Close();
return;
}
//SendString(TEXT("JOIN #fmh"));
FTimerHandle handle;
this->onIRCConnected();
}
void AGM_FullMetalHunters::JoinChannel(FString channel) {
SendCommand(TEXT("JOIN " + channel));
}
void AGM_FullMetalHunters::Disconnect()
{
SendCommand(TEXT("QUIT"));
}
bool AGM_FullMetalHunters::SendCommand(FString command)
{
FString serialized = command + TEXT("\r\n");
TCHAR *serializedChar = serialized.GetCharArray().GetData();
int32 size = FCString::Strlen(serializedChar);
int32 sent = 0;
return ListenerSocket->Send((uint8*)TCHAR_TO_UTF8(serializedChar), size, sent);
}
void AGM_FullMetalHunters::SendMessage(FString channel, FString message)
{
FDateTime now = FDateTime::Now();
SendCommand(TEXT("PRIVMSG " + channel + " :" + message));
FString concatenatedMessage = "[" + FString::FromInt(now.GetHour()) + ":" + FString::FromInt(now.GetMinute()) + ":" + FString::FromInt(now.GetSecond()) + "]" + userName + ": " + message;
this->onReceivedData(*concatenatedMessage);
}
Now, this works fine in a fresh project, but when I try to move it to my existing project, it crashes on standalone with this error:
[2017.11.07-21.23.03:063][ 0]LogWorld: Bringing up level for play took: 0.008137
[2017.11.07-21.23.03:779][ 0]LogWindows: Error: === Critical error: ===
[2017.11.07-21.23.03:779][ 0]LogWindows: Error:
[2017.11.07-21.23.03:779][ 0]LogWindows: Error: Fatal error!
[2017.11.07-21.23.03:779][ 0]LogWindows: Error:
[2017.11.07-21.23.03:779][ 0]LogWindows: Error: Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x00000000
[2017.11.07-21.23.03:779][ 0]LogWindows: Error:
[2017.11.07-21.23.03:779][ 0]LogWindows: Error: UE4Editor-FullMetalHunters-754.dll!AGM_FullMetalHunters::SendCommand() [c:\users\alexg\documents\unreal projects\fmh 4.16\source\fullmetalhunters\gm_fullmetalhunters.cpp:163]
[2017.11.07-21.23.03:779][ 0]LogWindows: Error: UE4Editor-FullMetalHunters-754.dll!AGM_FullMetalHunters::ConnectToServer() [c:\users\alexg\documents\unreal projects\fmh 4.16\source\fullmetalhunters\gm_fullmetalhunters.cpp:30]
[2017.11.07-21.23.03:779][ 0]LogWindows: Error: UE4Editor-FullMetalHunters-754.dll!AGM_FullMetalHunters::execConnectToServer() [c:\users\alexg\documents\unreal projects\fmh 4.16\source\fullmetalhunters\gm_fullmetalhunters.h:16]
I’ve attached the log file. Does anyone have any idea what’s going on?
(sorry for the long code)link text