diff --git a/Content/Assets/Items/MagneticShield_BP.uasset b/Content/Assets/Items/MagneticShield_BP.uasset index e6ea81e..8e0b956 100644 --- a/Content/Assets/Items/MagneticShield_BP.uasset +++ b/Content/Assets/Items/MagneticShield_BP.uasset Binary files differ diff --git a/Content/Assets/Items/OverCharge_BP.uasset b/Content/Assets/Items/OverCharge_BP.uasset new file mode 100644 index 0000000..0d7091f --- /dev/null +++ b/Content/Assets/Items/OverCharge_BP.uasset Binary files differ diff --git a/Content/Assets/NormieAsset/Test_anim.uasset b/Content/Assets/NormieAsset/Test_anim.uasset index 45dcab2..e8a8de8 100644 --- a/Content/Assets/NormieAsset/Test_anim.uasset +++ b/Content/Assets/NormieAsset/Test_anim.uasset Binary files differ diff --git a/Content/Levels/Sergio_Level.umap b/Content/Levels/Sergio_Level.umap index 3036d45..f7ddda5 100644 --- a/Content/Levels/Sergio_Level.umap +++ b/Content/Levels/Sergio_Level.umap Binary files differ diff --git a/Content/Matchmaking_Widget.uasset b/Content/Matchmaking_Widget.uasset new file mode 100644 index 0000000..7680607 --- /dev/null +++ b/Content/Matchmaking_Widget.uasset Binary files differ diff --git a/Content/NewGameMode_BP.uasset b/Content/NewGameMode_BP.uasset new file mode 100644 index 0000000..45ce29f --- /dev/null +++ b/Content/NewGameMode_BP.uasset Binary files differ diff --git a/Content/PlaneTest/BiPlane/NewPawn.uasset b/Content/PlaneTest/BiPlane/NewPawn.uasset new file mode 100644 index 0000000..d46df48 --- /dev/null +++ b/Content/PlaneTest/BiPlane/NewPawn.uasset Binary files differ diff --git a/Content/PlaneTest/Missile.uasset b/Content/PlaneTest/Missile.uasset index aa593b5..f0b9211 100644 --- a/Content/PlaneTest/Missile.uasset +++ b/Content/PlaneTest/Missile.uasset Binary files differ diff --git a/Content/PlaneTest/Projectile_BP.uasset b/Content/PlaneTest/Projectile_BP.uasset index c797cc7..cb93964 100644 --- a/Content/PlaneTest/Projectile_BP.uasset +++ b/Content/PlaneTest/Projectile_BP.uasset Binary files differ diff --git a/Content/PlaneTest/Targets_BP.uasset b/Content/PlaneTest/Targets_BP.uasset index 9f920bb..32caaa6 100644 --- a/Content/PlaneTest/Targets_BP.uasset +++ b/Content/PlaneTest/Targets_BP.uasset Binary files differ diff --git a/SkyFrontier.uproject b/SkyFrontier.uproject index d69af13..de53b0e 100644 --- a/SkyFrontier.uproject +++ b/SkyFrontier.uproject @@ -9,7 +9,8 @@ "Type": "Runtime", "LoadingPhase": "Default", "AdditionalDependencies": [ - "Engine" + "Engine", + "UMG" ] } ], @@ -19,11 +20,6 @@ "Enabled": true }, { - "Name": "UniversalCameraPlugin", - "Enabled": true, - "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/a9172fdfc87c464eae3a49860ee2610f" - }, - { "Name": "Landmass", "Enabled": true }, diff --git a/Source/SkyFrontier/Private/DamageSystem.cpp b/Source/SkyFrontier/Private/DamageSystem.cpp new file mode 100644 index 0000000..6ffce29 --- /dev/null +++ b/Source/SkyFrontier/Private/DamageSystem.cpp @@ -0,0 +1,54 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "DamageSystem.h" + +// Sets default values for this component's properties +UDamageSystem::UDamageSystem() +{ + PrimaryComponentTick.bCanEverTick = false; + PrimaryComponentTick.bStartWithTickEnabled = false; +} + + +// Called when the game starts +void UDamageSystem::BeginPlay() +{ + Super::BeginPlay(); + ShootingDamage = 20; + MissileDamage = 50; + +} + +float UDamageSystem::GetShootingDamage() const +{ + return ShootingDamage; +} + +float UDamageSystem::GetMissileDamage() const +{ + return MissileDamage; +} + +void UDamageSystem::MultiplyDamage(const float Amount) +{ + if(Amount >= 0) + { + ShootingDamage *= Amount; + MissileDamage *= Amount; + + OnIncreaseDamageEvent.Broadcast(Amount); + } +} + +void UDamageSystem::RestoreDamage(const float Amount) +{ + if(Amount >= 0) + { + ShootingDamage /= Amount; + MissileDamage /= Amount; + + OnIncreaseDamageEvent.Broadcast(Amount); + } +} + diff --git a/Source/SkyFrontier/Private/HealthSystem.cpp b/Source/SkyFrontier/Private/HealthSystem.cpp index 59e7244..3643f42 100644 --- a/Source/SkyFrontier/Private/HealthSystem.cpp +++ b/Source/SkyFrontier/Private/HealthSystem.cpp @@ -5,7 +5,6 @@ UHealthSystem::UHealthSystem() { - // This is a component that doesn't need a tick so lets disable it PrimaryComponentTick.bCanEverTick = false; PrimaryComponentTick.bStartWithTickEnabled = false; } @@ -13,8 +12,7 @@ void UHealthSystem::BeginPlay() { Super::BeginPlay(); - - MaxHealth = 100; + Health = MaxHealth; Shield = 0; } diff --git a/Source/SkyFrontier/Private/MyButton.cpp b/Source/SkyFrontier/Private/MyButton.cpp new file mode 100644 index 0000000..a4ba9cc --- /dev/null +++ b/Source/SkyFrontier/Private/MyButton.cpp @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "MyButton.h" + +UMyButton::UMyButton() +{ +OnClicked.AddDynamic(this, &UMyButton::OnClick); +} +void UMyButton::SetSessionInfo(int sID, TCPClient *tclient) +{ + sessionID = sID; tcpClient = tclient; +} +void UMyButton::OnClick() +{ + tcpClient->JoinGameSession(sessionID); +} \ No newline at end of file diff --git a/Source/SkyFrontier/Private/MyPlayerState.cpp b/Source/SkyFrontier/Private/MyPlayerState.cpp new file mode 100644 index 0000000..38f2d07 --- /dev/null +++ b/Source/SkyFrontier/Private/MyPlayerState.cpp @@ -0,0 +1,92 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "MyPlayerState.h" + +#include "MyButton.h" +#include "TCPClient.h" +#include "Blueprint/UserWidget.h" +#include "Components/Button.h" +#include "Components/ScrollBox.h" +#include "Components/TextBlock.h" +#include "Components/VerticalBox.h" +#include "Components/VerticalBoxSlot.h" + +void AMyPlayerState::BeginPlay() +{ + FString levelName = GetWorld()->GetMapName(); + levelName.RemoveFromStart(GetWorld()->StreamingLevelsPrefix); + if (levelName == "StartMap") + { + tcpClient = new TCPClient(this); + canConnectToGameServer = false; + if ((MatchmakingWidgetClass) && (tcpClient->IsConnected())) + { + serversList = new TArray(); + GetWorld()->GetTimerManager().SetTimer(serverListTimerHandle, this, &AMyPlayerState::OnUpdateServerList, 2, true); + MatchmakingWidget = CreateWidget(GetWorld(),MatchmakingWidgetClass); + MatchmakingWidget->AddToViewport(); + serverListScrollBoxWidget = Cast(MatchmakingWidget->GetWidgetFromName(TEXT("MyScrollBox"))); + UButton* newSessionButton = Cast(MatchmakingWidget->GetWidgetFromName(TEXT("NewSession"))); + if (newSessionButton) + { + newSessionButton->SetIsEnabled(true); + newSessionButton->OnClicked.AddDynamic(this, &AMyPlayerState::OnNewSessionClicked); + } + } + } +} +void AMyPlayerState::OnNewSessionClicked() +{ + tcpClient->CreateNewGameSession("My test session"); +} +void AMyPlayerState::UpdateSessionsList(FString serverinfo) +{ + TArray Out; serverinfo.ParseIntoArray(Out, TEXT("|"), true); + for (int i = 1; i < Out.Num() - 1; i += 2) { FSessionInfo *tempInfo = new FSessionInfo(); + tempInfo->id = FCString::Atoi(*Out[i]); + tempInfo->name = Out[i + 1]; + tempInfo->serverip = ""; + tempInfo->serverport = -1; + serversList->Add(tempInfo); } +} +void AMyPlayerState::ConnectToGameServer(FSessionInfo session) +{ + canConnectToGameServer = true; connectToGameServerSession = session; +} +void AMyPlayerState::OnUpdateServerList() { + if (tcpClient) { + if (tcpClient->IsConnected()) { + if (serversList->Num() > 0) { + if ((MatchmakingWidget) && (serverListScrollBoxWidget)) { + TArray allChildren = serverListScrollBoxWidget-> GetAllChildren(); + for (int i = 0; i < allChildren.Num(); i++) + { + allChildren[i]->RemoveFromParent(); + } + for (int i = 0; i < serversList->Num(); i++) + { + UVerticalBox* ItemWidgetsBox = NewObject(); + serverListScrollBoxWidget->AddChild(ItemWidgetsBox); + UMyButton* ItemWidget = NewObject(this); + ItemWidget->SetSessionInfo((*serversList)[i]->id, tcpClient); + UTextBlock* ItemWidgetText = NewObject(); + ItemWidgetText->SetText(FText::FromString( (*serversList)[i]->name)); + ItemWidget->AddChild(ItemWidgetText); + UVerticalBoxSlot* Slot = ItemWidgetsBox-> AddChildToVerticalBox(ItemWidget); + static FMargin Padding(5); + Slot->SetPadding(Padding); + } + } + } + if (canConnectToGameServer){ APlayerController* pController = GetWorld()-> GetFirstPlayerController(); + if (pController){ FString cmd = "open " + connectToGameServerSession.serverip + ":" + FString::FromInt(connectToGameServerSession.serverport); + tcpClient->Stop(); + canConnectToGameServer = false; + MatchmakingWidget->RemoveFromViewport(); + pController->ConsoleCommand(cmd); + } + } + } + } +} \ No newline at end of file diff --git a/Source/SkyFrontier/Private/TCPClient.cpp b/Source/SkyFrontier/Private/TCPClient.cpp new file mode 100644 index 0000000..82daf34 --- /dev/null +++ b/Source/SkyFrontier/Private/TCPClient.cpp @@ -0,0 +1,110 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "TCPClient.h" + +#include "MyPlayerState.h" +#include "Sockets.h" +#include "SocketSubsystem.h" +#include "Interfaces/IPv4/IPv4Address.h" +#include "TraceServices/Model/Diagnostics.h" + +TCPClient::TCPClient(AMyPlayerState* pState) +{ + Thread = FRunnableThread::Create(this, TEXT("TCPClientThread"), 0, TPri_Normal); PlayerState = pState; +} +TCPClient::~TCPClient() +{ + TCPClient::Stop(); delete Thread; +} +void TCPClient::Stop() +{ + running = false; +} +bool TCPClient::IsConnected() +{ + return connected; +} + +bool TCPClient::Init() +{ + Socket = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(NAME_Stream, TEXT("default"), false); + int32 NewSize = 0; + Socket->SetReceiveBufferSize(1024, NewSize); + FIPv4Address matchmakingServerIP(127, 0, 0, 1); + TSharedRef matchmakingServer = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr(); + matchmakingServer->SetIp(matchmakingServerIP.Value); + matchmakingServer->SetPort(8856); + + connected = Socket->Connect(*matchmakingServer); + if (connected) + { + UE_LOG(LogTemp, Log, TEXT("CONNECTED!")); + FString serialized = TEXT("g|#"); + TCHAR *serializedChar = serialized.GetCharArray().GetData(); + int32 size = FCString::Strlen(serializedChar); + int32 sent = 0; + bool successful = Socket->Send((uint8*)TCHAR_TO_UTF8(serializedChar), size, sent); + if (successful) + {UE_LOG(LogTemp, Log, TEXT("MESSAGE SENT!")); + return true; + } + else + { + UE_LOG(LogTemp, Log, TEXT("ERROR: NOT CONNECTED!"));return false; + } + } + return 0; +} + uint32 TCPClient::Run() + { + running = true; + TArray ReceivedData; + while (running) + { + uint32 Size = 0; + if (Socket->HasPendingData(Size)) + { + ReceivedData.Init(0, Size); + int32 Read = 0; + Socket->Recv(ReceivedData.GetData(), ReceivedData.Num(), Read); + FString ServerMessage = FString(UTF8_TO_TCHAR(ReceivedData.GetData())); + UE_LOG(LogTemp, Log, TEXT("RECEIVED: %s"), *ServerMessage); + if ((ServerMessage[0] == 's') && (PlayerState)) + { + PlayerState->UpdateSessionsList(ServerMessage); + } + else if((ServerMessage[0] == 'o') && (PlayerState)) + { + TArray Out; + ServerMessage.ParseIntoArray(Out, TEXT("|"), true); + FSessionInfo session; + session.id = -1; + session.name = ""; + session.serverip = Out[1]; + session.serverport = FCString::Atoi(*Out[2]); + PlayerState->ConnectToGameServer(session); + } + } + } + return 0; + } + + void TCPClient::CreateNewGameSession(FString sname) + { + FString serialized = "c|" + sname + "|#"; + TCHAR *serializedChar = serialized.GetCharArray().GetData(); + int32 size = FCString::Strlen(serializedChar); + int32 sent = 0; + bool successful = Socket->Send((uint8*) TCHAR_TO_UTF8(serializedChar), size, sent); + if (successful) UE_LOG(LogTemp, Log, TEXT("MESSAGE SENT!!!!")); + } + void TCPClient::JoinGameSession(int sID) + { + FString serialized = "j|" + FString::FromInt(sID) + "|#"; + TCHAR *serializedChar = serialized.GetCharArray().GetData(); + int32 size = FCString::Strlen(serializedChar); + int32 sent = 0; + bool successful = Socket->Send((uint8*) TCHAR_TO_UTF8(serializedChar), size, sent); + if (successful) UE_LOG(LogTemp, Log, TEXT("MESSAGE SENT!!!!")); + } \ No newline at end of file diff --git a/Source/SkyFrontier/Public/DamageSystem.h b/Source/SkyFrontier/Public/DamageSystem.h new file mode 100644 index 0000000..3f660d8 --- /dev/null +++ b/Source/SkyFrontier/Public/DamageSystem.h @@ -0,0 +1,45 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "DamageSystem.generated.h" + +DECLARE_EVENT_OneParam(UCPP_DamageComponent, IncreaseDamageEvent, float ) +DECLARE_EVENT_OneParam(UCPP_DamageComponent, DecreaseDamageEvent, float ) + +UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) +class SKYFRONTIER_API UDamageSystem : public UActorComponent +{ + GENERATED_BODY() + +public: + UDamageSystem(); + + UFUNCTION(BlueprintPure) + float GetShootingDamage() const; + UFUNCTION(BlueprintPure) + float GetMissileDamage() const; + + UFUNCTION(BlueprintCallable) + void MultiplyDamage(float Amount); + UFUNCTION(BlueprintCallable) + void RestoreDamage(float Amount); + +protected: + // Called when the game starts + virtual void BeginPlay() override; + +public: // Events + IncreaseDamageEvent OnIncreaseDamageEvent; + DecreaseDamageEvent OnDecreaseDamageEvent; + +private: // This can be protected if we want to subclass the Health Component + + UPROPERTY(EditAnywhere) + float ShootingDamage; + UPROPERTY(EditAnywhere) + float MissileDamage; + +}; diff --git a/Source/SkyFrontier/Public/MyButton.h b/Source/SkyFrontier/Public/MyButton.h new file mode 100644 index 0000000..57e7828 --- /dev/null +++ b/Source/SkyFrontier/Public/MyButton.h @@ -0,0 +1,26 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "TCPClient.h" +#include "Components/Button.h" +#include "MyButton.generated.h" + +/** + * + */ +UCLASS() +class SKYFRONTIER_API UMyButton : public UButton +{ + GENERATED_BODY() +public: + UMyButton(); + void SetSessionInfo(int sID, TCPClient *tclient); +protected: int sessionID; + TCPClient *tcpClient; + + UFUNCTION() + void OnClick(); + +}; diff --git a/Source/SkyFrontier/Public/MyPlayerState.h b/Source/SkyFrontier/Public/MyPlayerState.h new file mode 100644 index 0000000..816fe70 --- /dev/null +++ b/Source/SkyFrontier/Public/MyPlayerState.h @@ -0,0 +1,52 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/PlayerState.h" +#include "MyPlayerState.generated.h" + +USTRUCT() +struct FSessionInfo +{ + GENERATED_BODY() + UPROPERTY() + int id; + UPROPERTY() + FString name; + UPROPERTY() + FString serverip; + UPROPERTY() + int serverport; +}; + +UCLASS() +class SKYFRONTIER_API AMyPlayerState : public APlayerState +{ + GENERATED_BODY() +public: + void UpdateSessionsList(FString serverinfo); + void ConnectToGameServer(FSessionInfo session); + +protected: + virtual void BeginPlay() override; + + class TCPClient* tcpClient; + + UPROPERTY(EditDefaultsOnly, Category = "UI") + TSubclassOf MatchmakingWidgetClass; + class UUserWidget* MatchmakingWidget; + class UScrollBox* serverListScrollBoxWidget; + + TArray *serversList; + FTimerHandle serverListTimerHandle; + + bool canConnectToGameServer; + FSessionInfo connectToGameServerSession; + + UFUNCTION() + void OnNewSessionClicked(); + + UFUNCTION() + void OnUpdateServerList(); +}; diff --git a/Source/SkyFrontier/Public/TCPClient.h b/Source/SkyFrontier/Public/TCPClient.h new file mode 100644 index 0000000..5e83447 --- /dev/null +++ b/Source/SkyFrontier/Public/TCPClient.h @@ -0,0 +1,29 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" + +/** + * + */ +class SKYFRONTIER_API TCPClient : public FRunnable +{ +public: + TCPClient(class AMyPlayerState* pState); + ~TCPClient(); + virtual bool Init(); + virtual uint32 Run(); + virtual void Stop(); + void CreateNewGameSession(FString sname); + void JoinGameSession(int sID); + bool IsConnected(); + +private: + FRunnableThread* Thread; + FSocket* Socket; + FSocket* ListenerSocket; + bool running; + bool connected; + class AMyPlayerState* PlayerState; +}; diff --git a/Source/SkyFrontier/SkyFrontier.Build.cs b/Source/SkyFrontier/SkyFrontier.Build.cs index 89a0998..f2bbd8e 100644 --- a/Source/SkyFrontier/SkyFrontier.Build.cs +++ b/Source/SkyFrontier/SkyFrontier.Build.cs @@ -7,10 +7,10 @@ public SkyFrontier(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - - PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" }); - PrivateDependencyModuleNames.AddRange(new string[] { }); + PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "AIModule", "Sockets", "Networking", "UMG" }); + + PrivateDependencyModuleNames.AddRange(new string[] { "SessionServices", "TraceServices" }); // Uncomment if you are using Slate UI // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); diff --git a/Source/SkyFrontier/SkyFrontierGameModeBase.h b/Source/SkyFrontier/SkyFrontierGameModeBase.h index 15514a3..d38c45d 100644 --- a/Source/SkyFrontier/SkyFrontierGameModeBase.h +++ b/Source/SkyFrontier/SkyFrontierGameModeBase.h @@ -9,7 +9,7 @@ /** * */ -UCLASS() +UCLASS() class SKYFRONTIER_API ASkyFrontierGameModeBase : public AGameModeBase { GENERATED_BODY()