summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/AssetManager.cpp7
-rw-r--r--src/AssetManager.hpp2
-rw-r--r--src/Event.cpp33
-rw-r--r--src/Event.hpp96
-rw-r--r--src/GameState.cpp492
-rw-r--r--src/GameState.hpp49
-rw-r--r--src/Network.cpp4
-rw-r--r--src/NetworkClient.cpp9
-rw-r--r--src/NetworkClient.hpp1
-rw-r--r--src/Render.cpp129
-rw-r--r--src/Render.hpp5
-rw-r--r--src/Renderer.hpp14
-rw-r--r--src/RendererSection.cpp4
-rw-r--r--src/RendererSection.hpp2
-rw-r--r--src/RendererWorld.cpp158
-rw-r--r--src/RendererWorld.hpp22
-rw-r--r--src/Shader.cpp35
-rw-r--r--src/Stream.cpp6
-rw-r--r--src/ThreadGame.cpp75
-rw-r--r--src/ThreadGame.hpp3
-rw-r--r--src/ThreadNetwork.cpp36
-rw-r--r--src/ThreadNetwork.hpp2
-rw-r--r--src/Utility.cpp8
-rw-r--r--src/Utility.hpp2
-rw-r--r--src/World.cpp3
-rw-r--r--src/World.hpp4
26 files changed, 801 insertions, 400 deletions
diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp
index 351a118..28c08fa 100644
--- a/src/AssetManager.cpp
+++ b/src/AssetManager.cpp
@@ -37,6 +37,7 @@ void AssetManager::LoadTextureResources() {
std::string filename = index["meta"]["image"].get<std::string>();
float textureWidth = index["meta"]["size"]["w"].get<int>();
float textureHeight = index["meta"]["size"]["h"].get<int>();
+ size_t sizeName = 0,sizeTexture = 0;
for (auto &it:index["frames"]) {
auto frame = it["frame"];
TextureCoordinates coord;
@@ -47,9 +48,11 @@ void AssetManager::LoadTextureResources() {
std::string assetName = it["filename"].get<std::string>();
assetName.insert(0, "minecraft/textures/");
assetName.erase(assetName.length() - 4);
+ assetName.shrink_to_fit();
+ sizeName += sizeof(assetName) + assetName.capacity();
+ sizeTexture += sizeof(coord);
assetTextures[assetName] = coord;
}
-
textureAtlas = new Texture(filename);
LOG(INFO) << "Texture atlas id is " << textureAtlas->texture;
}
@@ -141,7 +144,7 @@ std::string AssetManager::GetTextureAssetNameByBlockId(BlockTextureId block) {
}
GLuint AssetManager::GetTextureAtlas() {
- return textureAtlas->texture;
+ return textureAtlas->texture;
}
TextureCoordinates AssetManager::GetTextureByBlock(BlockTextureId block) {
diff --git a/src/AssetManager.hpp b/src/AssetManager.hpp
index ba5546b..ca8bd35 100644
--- a/src/AssetManager.hpp
+++ b/src/AssetManager.hpp
@@ -24,7 +24,7 @@ struct TextureCoordinates {
return !(*this == TextureCoordinates(-1, -1, -1, -1));
}
- float x, y, w, h;
+ double x, y, w, h;
};
struct BlockTextureId {
diff --git a/src/Event.cpp b/src/Event.cpp
index e58a6f4..94eedba 100644
--- a/src/Event.cpp
+++ b/src/Event.cpp
@@ -19,13 +19,20 @@ void EventListener::PushEvent(Event event) {
eventsMutex.lock();
handlersMutex.lock();
if (handlers[event.type]) {
- //LOG(ERROR) << "Listener notified about event " << int(event.type);
events.push(event);
}
handlersMutex.unlock();
eventsMutex.unlock();
}
+void EventListener::DirectCall(Event event)
+{
+ handlersMutex.lock();
+ if (handlers[event.type])
+ handlers[event.type](event.data);
+ handlersMutex.unlock();
+}
+
bool EventListener::IsEventsQueueIsNotEmpty() {
eventsMutex.lock();
bool value = !events.empty();
@@ -74,20 +81,33 @@ void EventAgregator::PushEvent(EventType type, EventData data) {
Event event;
event.type = type;
event.data = data;
+ queueMutex.lock();
eventsToHandle.push(event);
+ queueMutex.unlock();
if (!isStarted) {
isStarted = true;
std::thread(&EventAgregator::EventHandlingLoop).detach();
}
}
+void EventAgregator::DirectEventCall(EventType type, EventData data)
+{
+ Event event {type, data};
+ listenersMutex.lock();
+ for (auto &listener : listeners) {
+ listenersMutex.unlock();
+ listener->DirectCall(event);
+ listenersMutex.lock();
+ }
+ listenersMutex.unlock();
+}
+
void EventAgregator::EventHandlingLoop() {
+ LoopExecutionTimeController timer(std::chrono::milliseconds(5));
while (true) {
queueMutex.lock();
if (!eventsToHandle.empty()) {
- auto queue = eventsToHandle;
- while (!eventsToHandle.empty())
- eventsToHandle.pop();
+ auto queue = std::move(eventsToHandle);
queueMutex.unlock();
while (!queue.empty()) {
@@ -103,9 +123,6 @@ void EventAgregator::EventHandlingLoop() {
queueMutex.lock();
}
queueMutex.unlock();
+ timer.Update();
}
-}
-
-void SetGlobalState(GlobalState state) {
- EventAgregator::PushEvent(EventType::GlobalAppState, GlobalAppStateData{state});
} \ No newline at end of file
diff --git a/src/Event.hpp b/src/Event.hpp
index c553058..232e6f2 100644
--- a/src/Event.hpp
+++ b/src/Event.hpp
@@ -9,6 +9,8 @@
#include <variant>
#include <functional>
+#include <SFML/Window.hpp>
+
#include "Vector.hpp"
#include "Packet.hpp"
#include "FSM.hpp"
@@ -18,13 +20,25 @@ enum class EventType {
ChunkChanged,
ConnectToServer,
ConnectionSuccessfull,
- GlobalAppState,
Disconnect,
RequestNetworkClient,
RegisterNetworkClient,
PlayerConnected,
RemoveLoadingScreen,
ConnectionFailed,
+ Exit,
+ Disconnected,
+ Connecting,
+ NetworkClientException,
+ MouseMoved,
+ KeyPressed,
+ KeyReleased,
+ InitalizeSectionRender,
+ UpdateSectionsRender,
+ CreateSectionRender,
+ CreatedSectionRender,
+ PlayerPosChanged,
+ DeleteSectionRender,
};
struct EchoData {
@@ -46,24 +60,8 @@ struct ConnectionSuccessfullData {
NetworkClient *ptr;
};
-enum class GlobalState {
- InitialLoading,
- MainMenu,
- Connecting,
- Loading,
- Playing,
- PauseMenu,
- Exiting,
-};
-
-void SetGlobalState(GlobalState state);
-
-struct GlobalAppStateData {
- GlobalState state;
-};
-
struct DisconnectData {
-
+ std::string reason;
};
struct SendPacketData {
@@ -96,9 +94,64 @@ struct ConnectionFailedData {
std::string reason;
};
+struct ExitData {
+
+};
+
+struct DisconnectedData {
+ std::string reason;
+};
+
+struct ConnectingData {
+
+};
+
+struct NetworkClientExceptionData {
+ std::string what;
+};
+
+struct MouseMovedData {
+ double x, y;
+};
+
+struct KeyPressedData {
+ sf::Keyboard::Key key;
+};
+
+struct KeyReleasedData {
+ sf::Keyboard::Key key;
+};
+
+struct InitalizeSectionRenderData {
+ Vector pos;
+};
+
+struct CreateSectionRenderData {
+ Vector pos;
+};
+
+struct CreatedSectionRenderData {
+ Vector pos;
+};
+
+struct PlayerPosChangedData {
+ Vector newPos;
+};
+
+struct UpdateSectionsRenderData {
+
+};
+
+struct DeleteSectionRenderData {
+ Vector pos;
+};
+
using EventData = std::variant<EchoData, ChunkChangedData, ConnectToServerData, ConnectionSuccessfullData,
- GlobalAppStateData, DisconnectData, SendPacketData, ReceivePacketData, RequestNetworkClientData,
- RegisterNetworkClientData, PlayerConnectedData, RemoveLoadingScreenData, ConnectionFailedData>;
+ DisconnectData, SendPacketData, ReceivePacketData, RequestNetworkClientData, RegisterNetworkClientData,
+ PlayerConnectedData, RemoveLoadingScreenData, ConnectionFailedData, ExitData, DisconnectedData,
+ ConnectingData, NetworkClientExceptionData, MouseMovedData, KeyPressedData, KeyReleasedData,
+ InitalizeSectionRenderData, CreateSectionRenderData, CreatedSectionRenderData, PlayerPosChangedData,
+ UpdateSectionsRenderData, DeleteSectionRenderData>;
struct Event {
EventType type;
@@ -120,6 +173,8 @@ class EventListener {
void PushEvent(Event event);
+ void DirectCall(Event event);
+
public:
EventListener();
~EventListener();
@@ -147,4 +202,5 @@ class EventAgregator {
public:
static void PushEvent(EventType type, EventData data);
+ static void DirectEventCall(EventType, EventData data);
}; \ No newline at end of file
diff --git a/src/GameState.cpp b/src/GameState.cpp
index a2c5182..52b5f0f 100644
--- a/src/GameState.cpp
+++ b/src/GameState.cpp
@@ -5,7 +5,6 @@ GameState::GameState(NetworkClient *networkClient) : nc(networkClient) {
Front = glm::vec3(0.0f, 0.0f, -1.0f);
this->SetPosition(glm::vec3(0.0f, 0.0f, 3.0f));
this->WorldUp = glm::vec3(0.0f, 1.0f, 0.0f);
- this->updateCameraVectors();
}
void GameState::Update(float deltaTime) {
@@ -44,7 +43,7 @@ void GameState::Update(float deltaTime) {
if (!isCollides) {
g_PlayerX += g_PlayerVelocityX * deltaTime;
g_PlayerZ += g_PlayerVelocityZ * deltaTime;
- }
+ }
const float AirResistance = 10.0f;
glm::vec3 vel(g_PlayerVelocityX, 0, g_PlayerVelocityZ);
@@ -53,259 +52,265 @@ void GameState::Update(float deltaTime) {
g_PlayerVelocityX = vel.x;
g_PlayerVelocityZ = vel.z;
}
+}
+void GameState::UpdatePacket()
+{
+ //Packet handling
+ auto ptr = nc->ReceivePacket();
+ if (ptr) {
+ switch ((PacketNamePlayCB)ptr->GetPacketId()) {
+ case SpawnObject:
+ break;
+ case SpawnExperienceOrb:
+ break;
+ case SpawnGlobalEntity:
+ break;
+ case SpawnMob:
+ break;
+ case SpawnPainting:
+ break;
+ case SpawnPlayer:
+ break;
+ case AnimationCB:
+ break;
+ case Statistics:
+ break;
+ case BlockBreakAnimation:
+ break;
+ case UpdateBlockEntity:
+ break;
+ case BlockAction:
+ break;
+ case BlockChange:
+ break;
+ case BossBar:
+ break;
+ case ServerDifficulty:
+ break;
+ case TabCompleteCB:
+ break;
+ case ChatMessageCB:
+ break;
+ case MultiBlockChange:
+ break;
+ case ConfirmTransactionCB:
+ break;
+ case CloseWindowCB:
+ break;
+ case OpenWindow:
+ break;
+ case WindowItems:
+ break;
+ case WindowProperty:
+ break;
+ case SetSlot:
+ break;
+ case SetCooldown:
+ break;
+ case PluginMessageCB:
+ break;
+ case NamedSoundEffect:
+ break;
+ case DisconnectPlay: {
+ auto packet = std::static_pointer_cast<PacketDisconnectPlay>(ptr);
+ LOG(INFO) << "Disconnect reason: " << packet->Reason;
+ EventAgregator::PushEvent(EventType::Disconnect, DisconnectData{ packet->Reason });
+ break;
+ }
+ case EntityStatus:
+ break;
+ case Explosion:
+ break;
+ case UnloadChunk:
+ break;
+ case ChangeGameState:
+ break;
+ case KeepAliveCB:
+ LOG(WARNING) << "Receive KeepAlive packet in GameState handler";
+ break;
+ case ChunkData: {
+ auto packet = std::static_pointer_cast<PacketChunkData>(ptr);
+ world.ParseChunkData(packet);
+ break;
+ }
+ case Effect:
+ break;
+ case Particle:
+ break;
+ case JoinGame: {
+ auto packet = std::static_pointer_cast<PacketJoinGame>(ptr);
+ g_PlayerEid = packet->EntityId;
+ g_Gamemode = (packet->Gamemode & 0b11111011);
+ g_Dimension = packet->Dimension;
+ g_Difficulty = packet->Difficulty;
+ g_MaxPlayers = packet->MaxPlayers;
+ g_LevelType = packet->LevelType;
+ g_ReducedDebugInfo = packet->ReducedDebugInfo;
+ LOG(INFO) << "Gamemode is " << g_Gamemode << ", Difficulty is " << (int)g_Difficulty
+ << ", Level Type is " << g_LevelType;
+ EventAgregator::PushEvent(EventType::PlayerConnected, PlayerConnectedData{ this });
+ break;
+ }
+ case Map:
+ break;
+ case EntityRelativeMove:
+ break;
+ case EntityLookAndRelativeMove:
+ break;
+ case EntityLook:
+ break;
+ case Entity:
+ break;
+ case VehicleMove:
+ break;
+ case OpenSignEditor:
+ break;
+ case PlayerAbilitiesCB:
+ break;
+ case CombatEvent:
+ break;
+ case PlayerListItem:
+ break;
+ case PlayerPositionAndLookCB: {
+ auto packet = std::static_pointer_cast<PacketPlayerPositionAndLookCB>(ptr);
+ if ((packet->Flags & 0x10) != 0) {
+ g_PlayerPitch += packet->Pitch;
+ }
+ else {
+ g_PlayerPitch = packet->Pitch;
+ };
- //Packet handling
- auto ptr = nc->ReceivePacket();
- while (ptr != nullptr) {
- switch ((PacketNamePlayCB) ptr->GetPacketId()) {
- case SpawnObject:
- break;
- case SpawnExperienceOrb:
- break;
- case SpawnGlobalEntity:
- break;
- case SpawnMob:
- break;
- case SpawnPainting:
- break;
- case SpawnPlayer:
- break;
- case AnimationCB:
- break;
- case Statistics:
- break;
- case BlockBreakAnimation:
- break;
- case UpdateBlockEntity:
- break;
- case BlockAction:
- break;
- case BlockChange:
- break;
- case BossBar:
- break;
- case ServerDifficulty:
- break;
- case TabCompleteCB:
- break;
- case ChatMessageCB:
- break;
- case MultiBlockChange:
- break;
- case ConfirmTransactionCB:
- break;
- case CloseWindowCB:
- break;
- case OpenWindow:
- break;
- case WindowItems:
- break;
- case WindowProperty:
- break;
- case SetSlot:
- break;
- case SetCooldown:
- break;
- case PluginMessageCB:
- break;
- case NamedSoundEffect:
- break;
- case DisconnectPlay: {
- auto packet = std::static_pointer_cast<PacketDisconnectPlay>(ptr);
- LOG(INFO) << "Disconnect reason: " << packet->Reason;
- EventAgregator::PushEvent(EventType::GlobalAppState, GlobalAppStateData{GlobalState::Exiting});
- break;
- }
- case EntityStatus:
- break;
- case Explosion:
- break;
- case UnloadChunk:
- break;
- case ChangeGameState:
- break;
- case KeepAliveCB:
- LOG(WARNING) << "Receive KeepAlive packet in GameState handler";
- break;
- case ChunkData: {
- auto packet = std::static_pointer_cast<PacketChunkData>(ptr);
- world.ParseChunkData(packet);
- break;
- }
- case Effect:
- break;
- case Particle:
- break;
- case JoinGame: {
- auto packet = std::static_pointer_cast<PacketJoinGame>(ptr);
- g_PlayerEid = packet->EntityId;
- g_Gamemode = (packet->Gamemode & 0b11111011);
- g_Dimension = packet->Dimension;
- g_Difficulty = packet->Difficulty;
- g_MaxPlayers = packet->MaxPlayers;
- g_LevelType = packet->LevelType;
- g_ReducedDebugInfo = packet->ReducedDebugInfo;
- LOG(INFO) << "Gamemode is " << g_Gamemode << ", Difficulty is " << (int) g_Difficulty
- << ", Level Type is " << g_LevelType;
- SetGlobalState(GlobalState::Loading);
- EventAgregator::PushEvent(EventType::PlayerConnected, PlayerConnectedData{this});
- break;
- }
- case Map:
- break;
- case EntityRelativeMove:
- break;
- case EntityLookAndRelativeMove:
- break;
- case EntityLook:
- break;
- case Entity:
- break;
- case VehicleMove:
- break;
- case OpenSignEditor:
- break;
- case PlayerAbilitiesCB:
- break;
- case CombatEvent:
- break;
- case PlayerListItem:
- break;
- case PlayerPositionAndLookCB: {
- auto packet = std::static_pointer_cast<PacketPlayerPositionAndLookCB>(ptr);
- if ((packet->Flags & 0x10) != 0) {
- g_PlayerPitch += packet->Pitch;
- } else {
- g_PlayerPitch = packet->Pitch;
- };
-
- if ((packet->Flags & 0x08) != 0) {
- g_PlayerYaw += packet->Yaw;
- } else {
- g_PlayerYaw = packet->Yaw;
- }
+ if ((packet->Flags & 0x08) != 0) {
+ g_PlayerYaw += packet->Yaw;
+ }
+ else {
+ g_PlayerYaw = packet->Yaw;
+ }
- if ((packet->Flags & 0x01) != 0) {
- g_PlayerX += packet->X;
- } else {
- g_PlayerX = packet->X;
- }
+ if ((packet->Flags & 0x01) != 0) {
+ g_PlayerX += packet->X;
+ }
+ else {
+ g_PlayerX = packet->X;
+ }
- if ((packet->Flags & 0x02) != 0) {
- g_PlayerY += packet->Y;
- } else {
- g_PlayerY = packet->Y;
- }
+ if ((packet->Flags & 0x02) != 0) {
+ g_PlayerY += packet->Y;
+ }
+ else {
+ g_PlayerY = packet->Y;
+ }
- if ((packet->Flags & 0x04) != 0) {
- g_PlayerZ += packet->Z;
- } else {
- g_PlayerZ = packet->Z;
- }
+ if ((packet->Flags & 0x04) != 0) {
+ g_PlayerZ += packet->Z;
+ }
+ else {
+ g_PlayerZ = packet->Z;
+ }
- //if (!g_IsGameStarted)
- LOG(INFO) << "PlayerPos is " << g_PlayerX << ", " << g_PlayerY << ", " << g_PlayerZ << "\t\tAngle: "
- << g_PlayerYaw << "," << g_PlayerPitch;
+ EventAgregator::PushEvent(EventType::PlayerPosChanged, PlayerPosChangedData{ Vector(g_PlayerX,g_PlayerY,g_PlayerZ) });
+ LOG(INFO) << "PlayerPos is " << g_PlayerX << ", " << g_PlayerY << ", " << g_PlayerZ << "\t\tAngle: "
+ << g_PlayerYaw << "," << g_PlayerPitch;
- if (!g_IsGameStarted) {
- LOG(INFO) << "Game is started";
- EventAgregator::PushEvent(EventType::RemoveLoadingScreen, RemoveLoadingScreenData{});
- SetGlobalState(GlobalState::Playing);
- }
+ if (!g_IsGameStarted) {
+ LOG(INFO) << "Game is started";
+ EventAgregator::PushEvent(EventType::RemoveLoadingScreen, RemoveLoadingScreenData{});
+ }
- g_IsGameStarted = true;
+ g_IsGameStarted = true;
- auto packetResponse = std::make_shared<PacketTeleportConfirm>(packet->TeleportId);
- auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0);
+ auto packetResponse = std::make_shared<PacketTeleportConfirm>(packet->TeleportId);
+ auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0);
- nc->SendPacket(packetResponse);
- nc->SendPacket(packetPerformRespawn);
- break;
- }
- case UseBed:
- break;
- case UnlockRecipes:
- break;
- case DestroyEntities:
- break;
- case RemoveEntityEffect:
- break;
- case ResourcePackSend:
- break;
- case Respawn:
- break;
- case EntityHeadLook:
- break;
- case SelectAdvancementTab:
- break;
- case WorldBorder:
- break;
- case Camera:
- break;
- case HeldItemChangeCB:
- break;
- case DisplayScoreboard:
- break;
- case EntityMetadata:
- break;
- case AttachEntity:
- break;
- case EntityVelocity:
- break;
- case EntityEquipment:
- break;
- case SetExperience:
- break;
- case UpdateHealth: {
- auto packet = std::static_pointer_cast<PacketUpdateHealth>(ptr);
- g_PlayerHealth = packet->Health;
- if (g_PlayerHealth <= 0) {
- LOG(INFO) << "Player is dead. Respawning...";
- auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0);
- nc->SendPacket(packetPerformRespawn);
- }
- break;
- }
- case ScoreboardObjective:
- break;
- case SetPassengers:
- break;
- case Teams:
- break;
- case UpdateScore:
- break;
- case SpawnPosition: {
- auto packet = std::static_pointer_cast<PacketSpawnPosition>(ptr);
- g_SpawnPosition = packet->Location;
- LOG(INFO) << "Spawn position is " << g_SpawnPosition.GetX() << "," << g_SpawnPosition.GetY() << ","
- << g_SpawnPosition.GetZ();
- break;
- }
- case TimeUpdate:
- break;
- case Title:
- break;
- case SoundEffect:
- break;
- case PlayerListHeaderAndFooter:
- break;
- case CollectItem:
- break;
- case EntityTeleport:
- break;
- case Advancements:
- break;
- case EntityProperties:
- break;
- case EntityEffect:
- break;
- }
- ptr = nc->ReceivePacket();
- }
+ nc->SendPacket(packetResponse);
+ nc->SendPacket(packetPerformRespawn);
+ break;
+ }
+ case UseBed:
+ break;
+ case UnlockRecipes:
+ break;
+ case DestroyEntities:
+ break;
+ case RemoveEntityEffect:
+ break;
+ case ResourcePackSend:
+ break;
+ case Respawn:
+ break;
+ case EntityHeadLook:
+ break;
+ case SelectAdvancementTab:
+ break;
+ case WorldBorder:
+ break;
+ case Camera:
+ break;
+ case HeldItemChangeCB:
+ break;
+ case DisplayScoreboard:
+ break;
+ case EntityMetadata:
+ break;
+ case AttachEntity:
+ break;
+ case EntityVelocity:
+ break;
+ case EntityEquipment:
+ break;
+ case SetExperience:
+ break;
+ case UpdateHealth: {
+ auto packet = std::static_pointer_cast<PacketUpdateHealth>(ptr);
+ g_PlayerHealth = packet->Health;
+ if (g_PlayerHealth <= 0) {
+ LOG(INFO) << "Player is dead. Respawning...";
+ auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0);
+ nc->SendPacket(packetPerformRespawn);
+ }
+ break;
+ }
+ case ScoreboardObjective:
+ break;
+ case SetPassengers:
+ break;
+ case Teams:
+ break;
+ case UpdateScore:
+ break;
+ case SpawnPosition: {
+ auto packet = std::static_pointer_cast<PacketSpawnPosition>(ptr);
+ g_SpawnPosition = packet->Location;
+ LOG(INFO) << "Spawn position is " << g_SpawnPosition.GetX() << "," << g_SpawnPosition.GetY() << ","
+ << g_SpawnPosition.GetZ();
+ break;
+ }
+ case TimeUpdate:
+ break;
+ case Title:
+ break;
+ case SoundEffect:
+ break;
+ case PlayerListHeaderAndFooter:
+ break;
+ case CollectItem:
+ break;
+ case EntityTeleport:
+ break;
+ case Advancements:
+ break;
+ case EntityProperties:
+ break;
+ case EntityEffect:
+ break;
+ }
+ }
}
void GameState::HandleMovement(GameState::Direction direction, float deltaTime) {
+ if (!g_IsGameStarted)
+ return;
const float PlayerSpeed = 40.0;
float velocity = PlayerSpeed * deltaTime;
glm::vec3 vel(g_PlayerVelocityX, g_PlayerVelocityY, g_PlayerVelocityZ);
@@ -339,6 +344,8 @@ void GameState::HandleMovement(GameState::Direction direction, float deltaTime)
}
void GameState::HandleRotation(double yaw, double pitch) {
+ if (!g_IsGameStarted)
+ return;
this->SetYaw(Yaw() + yaw);
this->SetPitch(Pitch() + pitch);
if (this->Pitch() > 89.0f)
@@ -352,6 +359,7 @@ void GameState::HandleRotation(double yaw, double pitch) {
}
glm::mat4 GameState::GetViewMatrix() {
+ updateCameraVectors();
auto pos = this->Position();
pos.y += 1.62;
return glm::lookAt(pos, pos + this->Front, this->Up);
diff --git a/src/GameState.hpp b/src/GameState.hpp
index dbe8f9d..d104e54 100644
--- a/src/GameState.hpp
+++ b/src/GameState.hpp
@@ -16,7 +16,8 @@ public:
void Update(float deltaTime);
- //Navigation
+ void UpdatePacket();
+
enum Direction {
FORWARD, BACKWARD, LEFT, RIGHT, JUMP
};
@@ -37,33 +38,31 @@ public:
glm::vec3 Right;
glm::vec3 WorldUp;
- //Everything other
World world;
- //bool &isRunning;
- std::string g_PlayerUuid;
- std::string g_PlayerName;
- bool g_IsGameStarted;
- int g_PlayerEid;
- int g_Gamemode;
- int g_Dimension;
- byte g_Difficulty;
- byte g_MaxPlayers;
- std::string g_LevelType;
- bool g_ReducedDebugInfo;
+ std::string g_PlayerUuid = "";
+ std::string g_PlayerName = "";
+ bool g_IsGameStarted = false;
+ int g_PlayerEid = 0;
+ int g_Gamemode = 0;
+ int g_Dimension = 0;
+ byte g_Difficulty = 0;
+ byte g_MaxPlayers = 0;
+ std::string g_LevelType = "";
+ bool g_ReducedDebugInfo = false;
Vector g_SpawnPosition;
- bool g_PlayerInvulnerable;
- bool g_PlayerFlying;
- bool g_PlayerAllowFlying;
- bool g_PlayerCreativeMode;
- float g_PlayerFlyingSpeed;
- float g_PlayerFovModifier;
- float g_PlayerPitch;
- float g_PlayerYaw;
- double g_PlayerX;
- double g_PlayerY;
- double g_PlayerZ;
- float g_PlayerHealth;
+ bool g_PlayerInvulnerable = false;
+ bool g_PlayerFlying = false;
+ bool g_PlayerAllowFlying = false;
+ bool g_PlayerCreativeMode = false;
+ float g_PlayerFlyingSpeed = 0;
+ float g_PlayerFovModifier = 0;
+ float g_PlayerPitch = 0;
+ float g_PlayerYaw = 0;
+ double g_PlayerX = 0;
+ double g_PlayerY = 0;
+ double g_PlayerZ = 0;
+ float g_PlayerHealth = 0;
bool g_OnGround = true;
double g_PlayerVelocityX = 0;
diff --git a/src/Network.cpp b/src/Network.cpp
index 47ae751..62ad1f9 100644
--- a/src/Network.cpp
+++ b/src/Network.cpp
@@ -4,14 +4,14 @@ Network::Network(std::string address, unsigned short port) {
try {
socket = new Socket(address, port);
} catch (std::exception &e) {
- LOG(WARNING) << "CONNECT FAULT";
+ LOG(WARNING) << "Connection failed: " << e.what();
throw;
}
try {
stream = new StreamSocket(socket);
} catch (std::exception &e) {
- LOG(WARNING) << "NOT STREAMED";
+ LOG(WARNING) << "Stream creation failed: " << e.what();
}
}
diff --git a/src/NetworkClient.cpp b/src/NetworkClient.cpp
index d944f54..5877952 100644
--- a/src/NetworkClient.cpp
+++ b/src/NetworkClient.cpp
@@ -51,7 +51,8 @@ void NetworkClient::SendPacket(std::shared_ptr<Packet> packet) {
void NetworkClient::NetworkLoop() {
auto timeOfLastKeepAlivePacket = std::chrono::steady_clock::now();
el::Helpers::setThreadName("Network");
- LOG(INFO) << "Network thread is started";
+ bool validEnded = true;
+
try {
while (isActive) {
toSendMutex.lock();
@@ -85,7 +86,7 @@ void NetworkClient::NetworkLoop() {
}
}
} catch (std::exception &e) {
- LOG(ERROR) << "Exception catched in NetworkLoop: " << e.what();
+ EventAgregator::PushEvent(EventType::NetworkClientException, NetworkClientExceptionData{ e.what() });
+ validEnded = false;
}
- LOG(INFO) << "Network thread is stopped";
-}
+} \ No newline at end of file
diff --git a/src/NetworkClient.hpp b/src/NetworkClient.hpp
index 83db517..9acae84 100644
--- a/src/NetworkClient.hpp
+++ b/src/NetworkClient.hpp
@@ -5,6 +5,7 @@
#include <mutex>
#include "Network.hpp"
+#include "Event.hpp"
class NetworkClient {
Network network;
diff --git a/src/Render.cpp b/src/Render.cpp
index 9121d1a..38a6ab0 100644
--- a/src/Render.cpp
+++ b/src/Render.cpp
@@ -30,6 +30,8 @@ void Render::InitSfml(unsigned int WinWidth, unsigned int WinHeight, std::string
window->setPosition(sf::Vector2i(sf::VideoMode::getDesktopMode().width / 2 - window->getSize().x / 2,
sf::VideoMode::getDesktopMode().height / 2 - window->getSize().y / 2));
SetMouseCapture(false);
+ renderState.WindowWidth = WinWidth;
+ renderState.WindowHeight = WinHeight;
}
void Render::InitGlew() {
@@ -51,19 +53,18 @@ void Render::InitGlew() {
}
void Render::PrepareToRendering() {
- shader = new Shader("./shaders/face.vs", "./shaders/face.fs");
- shader->Use();
-
//TextureAtlas texture
glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, AssetManager::Instance().GetTextureAtlas());
- glUniform1i(glGetUniformLocation(shader->Program, "textureAtlas"), 0);
+ glBindTexture(GL_TEXTURE_2D, AssetManager::Instance().GetTextureAtlas());
}
void Render::RenderFrame() {
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ if (renderWorld)
+ world->Render(renderState);
+
window->display();
}
@@ -77,33 +78,78 @@ void Render::HandleEvents() {
break;
case sf::Event::Resized:
glViewport(0, 0, window->getSize().x, window->getSize().y);
+ renderState.WindowWidth = window->getSize().x;
+ renderState.WindowHeight = window->getSize().y;
break;
case sf::Event::KeyPressed:
if (!window->hasFocus()) break;
- switch (event.key.code) {
- case sf::Keyboard::Escape:
- LOG(INFO) << "Received close event by esc";
- isRunning = false;
- break;
- case sf::Keyboard::T:
- SetMouseCapture(!isMouseCaptured);
- break;
- case sf::Keyboard::U:
- EventAgregator::PushEvent(EventType::ConnectToServer, ConnectToServerData{"127.0.0.1", 25565});
+ switch (event.key.code) {
+ case sf::Keyboard::Escape:
+ LOG(INFO) << "Received close event by esc";
+ isRunning = false;
+ break;
+ case sf::Keyboard::T:
+ SetMouseCapture(!isMouseCaptured);
+ break;
+ case sf::Keyboard::U:
+ EventAgregator::PushEvent(EventType::ConnectToServer, ConnectToServerData{ "127.0.0.1", 25565 });
+ break;
+ case sf::Keyboard::I:
+ EventAgregator::PushEvent(EventType::Disconnect, DisconnectData{ "Manual disconnect" });
+ break;
+ case sf::Keyboard::K:
+ if (renderWorld) {
+ world->MaxRenderingDistance--;
+ if (world->MaxRenderingDistance <= 0)
+ world->MaxRenderingDistance = 1;
+ LOG(INFO) << "Decreased rendering distance: " << world->MaxRenderingDistance;
+ EventAgregator::PushEvent(EventType::UpdateSectionsRender, UpdateSectionsRenderData{});
+ }
+ break;
+ case sf::Keyboard::L:
+ if (renderWorld) {
+ world->MaxRenderingDistance++;
+ LOG(INFO) << "Increased rendering distance: " << world->MaxRenderingDistance;
+ EventAgregator::PushEvent(EventType::UpdateSectionsRender, UpdateSectionsRenderData{});
+ }
+ break;
+ case sf::Keyboard::W:
+ EventAgregator::PushEvent(EventType::KeyPressed, KeyPressedData{ sf::Keyboard::W });
+ break;
+ case sf::Keyboard::A:
+ EventAgregator::PushEvent(EventType::KeyPressed, KeyPressedData{ sf::Keyboard::A });
+ break;
+ case sf::Keyboard::S:
+ EventAgregator::PushEvent(EventType::KeyPressed, KeyPressedData{ sf::Keyboard::S });
+ break;
+ case sf::Keyboard::D:
+ EventAgregator::PushEvent(EventType::KeyPressed, KeyPressedData{ sf::Keyboard::D });
+ break;
default:
break;
}
+ case sf::Event::KeyReleased:
+ if (!window->hasFocus()) break;
+ switch (event.key.code) {
+ case sf::Keyboard::W:
+ EventAgregator::PushEvent(EventType::KeyReleased, KeyReleasedData{ sf::Keyboard::W });
+ break;
+ case sf::Keyboard::A:
+ EventAgregator::PushEvent(EventType::KeyReleased, KeyReleasedData{ sf::Keyboard::A });
+ break;
+ case sf::Keyboard::S:
+ EventAgregator::PushEvent(EventType::KeyReleased, KeyReleasedData{ sf::Keyboard::S });
+ break;
+ case sf::Keyboard::D:
+ EventAgregator::PushEvent(EventType::KeyReleased, KeyReleasedData{ sf::Keyboard::D });
+ break;
+ default:
+ break;
+ }
default:
break;
}
- }
- if (window->hasFocus()) {
- /*if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) gameState->HandleMovement(GameState::FORWARD, deltaTime);
- if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) gameState->HandleMovement(GameState::BACKWARD, deltaTime);
- if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) gameState->HandleMovement(GameState::LEFT, deltaTime);
- if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) gameState->HandleMovement(GameState::RIGHT, deltaTime);
- if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space)) gameState->HandleMovement(GameState::JUMP, deltaTime);*/
- }
+ }
}
void Render::HandleMouseCapture() {
@@ -112,7 +158,7 @@ void Render::HandleMouseCapture() {
sf::Mouse::setPosition(center, *window);
mouseXDelta = (mousePos - center).x, mouseYDelta = (center - mousePos).y;
const float Sensetivity = 0.7f;
- //gameState->HandleRotation(mouseXDelta * Sensetivity, mouseYDelta * Sensetivity);
+ EventAgregator::DirectEventCall(EventType::MouseMoved, MouseMovedData{ mouseXDelta * Sensetivity, mouseYDelta });
}
void Render::SetMouseCapture(bool IsCaptured) {
@@ -125,11 +171,7 @@ void Render::SetMouseCapture(bool IsCaptured) {
void Render::ExecuteRenderLoop() {
EventListener listener;
- listener.RegisterHandler(EventType::GlobalAppState, [this](EventData eventData) {
-
- });
-
- /*listener.RegisterHandler(EventType::ConnectionSuccessfull, [this](EventData eventData) {
+ listener.RegisterHandler(EventType::ConnectionSuccessfull, [this](EventData eventData) {
auto data = std::get<ConnectionSuccessfullData>(eventData);
window->setTitle("Connected");
});
@@ -137,14 +179,31 @@ void Render::ExecuteRenderLoop() {
listener.RegisterHandler(EventType::PlayerConnected, [this](EventData eventData) {
auto data = std::get<PlayerConnectedData>(eventData);
window->setTitle("Joined the game");
+ world = std::make_unique<RendererWorld>(data.ptr);
});
listener.RegisterHandler(EventType::RemoveLoadingScreen, [this](EventData eventData) {
- window->setTitle("Loaded");
- });*/
+ window->setTitle("Playing");
+ renderWorld = true;
+ });
+
+ listener.RegisterHandler(EventType::ConnectionFailed, [this](EventData eventData) {
+ window->setTitle("Connection failed: " + std::get<ConnectionFailedData>(eventData).reason);
+ renderWorld = false;
+ world.reset();
+ });
- using namespace std::chrono_literals;
- LoopExecutionTimeController timer(16ms);
+ listener.RegisterHandler(EventType::Disconnected, [this](EventData eventData) {
+ window->setTitle("Disconnected: " + std::get<DisconnectedData>(eventData).reason);
+ renderWorld = false;
+ world.reset();
+ });
+
+ listener.RegisterHandler(EventType::Connecting, [this](EventData eventData) {
+ window->setTitle("Connecting");
+ });
+
+ LoopExecutionTimeController timer(std::chrono::milliseconds(16));
while (isRunning) {
HandleEvents();
if (isMouseCaptured) HandleMouseCapture();
@@ -153,7 +212,9 @@ void Render::ExecuteRenderLoop() {
RenderFrame();
while (listener.IsEventsQueueIsNotEmpty())
listener.HandleEvent();
+ if (renderWorld)
+ window->setTitle("FPS: "+std::to_string(1.0/timer.GetDeltaMs()*1000.0));
timer.Update();
}
- SetGlobalState(GlobalState::Exiting);
+ EventAgregator::PushEvent(EventType::Exit, ExitData{});
}
diff --git a/src/Render.hpp b/src/Render.hpp
index 636c4c7..83b3d1a 100644
--- a/src/Render.hpp
+++ b/src/Render.hpp
@@ -3,13 +3,16 @@
#include <SFML/Window.hpp>
#include "Shader.hpp"
+#include "RendererWorld.hpp"
class Render {
sf::Window *window;
bool isRunning=true;
bool isMouseCaptured = false;
float mouseXDelta, mouseYDelta;
- Shader *shader;
+ std::unique_ptr<RendererWorld> world;
+ bool renderWorld = false;
+ RenderState renderState;
void SetMouseCapture(bool IsCaptured);
diff --git a/src/Renderer.hpp b/src/Renderer.hpp
index 81c5c50..de2e331 100644
--- a/src/Renderer.hpp
+++ b/src/Renderer.hpp
@@ -3,16 +3,18 @@
#include <GL/glew.h>
class RenderState {
- GLuint ActiveVao;
- GLuint ActiveShader;
+ GLuint ActiveVao = 0;
+ GLuint ActiveShader = 0;
public:
void SetActiveVao(GLuint Vao);
void SetActiveShader(GLuint Shader);
+ unsigned int WindowWidth, WindowHeight;
};
struct Renderer {
- virtual ~Renderer() = default;
- virtual void Render(RenderState& renderState) = 0;
- virtual void PrepareResources() = 0;
- virtual void PrepareRender() = 0;
+ virtual ~Renderer() = default;
+ virtual void Render(RenderState& renderState) = 0;
+ virtual void PrepareResources() = 0;
+ virtual void PrepareRender() = 0;
+ virtual bool IsNeedResourcesPrepare() = 0;
}; \ No newline at end of file
diff --git a/src/RendererSection.cpp b/src/RendererSection.cpp
index 62a0dc7..fbb9c19 100644
--- a/src/RendererSection.cpp
+++ b/src/RendererSection.cpp
@@ -172,7 +172,7 @@ void RendererSection::SetEnabled(bool isEnabled) {
this->isEnabled = isEnabled;
}
-bool RendererSection::IsNeedUpdate() {
+bool RendererSection::IsNeedResourcesPrepare() {
size_t currentHash = world->GetSection(sectionPosition).GetHash();
bool isNeedUpdate = currentHash != hash;
return isNeedUpdate;
@@ -188,7 +188,7 @@ void RendererSection::PrepareResources() {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
Vector blockPos = Vector(x, y, z) + (sectionPosition * 16);
- Block &block = world->GetBlock(blockPos);
+ Block block = world->GetBlock(blockPos);
if (block.id == 0)
continue;
diff --git a/src/RendererSection.hpp b/src/RendererSection.hpp
index 093a977..c165da4 100644
--- a/src/RendererSection.hpp
+++ b/src/RendererSection.hpp
@@ -45,5 +45,5 @@ public:
Section *GetSection();
- bool IsNeedUpdate();
+ bool IsNeedResourcesPrepare() override;
}; \ No newline at end of file
diff --git a/src/RendererWorld.cpp b/src/RendererWorld.cpp
index c80250c..2ec621a 100644
--- a/src/RendererWorld.cpp
+++ b/src/RendererWorld.cpp
@@ -1 +1,159 @@
#include "RendererWorld.hpp"
+
+void RendererWorld::LoadedSectionController() {
+
+ std::function<void(Vector)> updateAllSections = [this](Vector playerPos) {
+ Vector playerChunk(std::floor(gs->g_PlayerX / 16), 0, std::floor(gs->g_PlayerZ / 16));
+
+ std::vector<Vector> suitableChunks;
+ for (auto& it : gs->world.GetSectionsList()) {
+ double distance = (Vector(it.GetX(),0,it.GetZ()) - playerChunk).GetMagnitude();
+ if (distance > MaxRenderingDistance)
+ continue;
+ suitableChunks.push_back(it);
+ }
+
+ std::vector<Vector> toRemove;
+
+ sectionsMutex.lock();
+ for (auto& it : sections) {
+ if (std::find(suitableChunks.begin(), suitableChunks.end(), it.first) == suitableChunks.end())
+ toRemove.push_back(it.first);
+ }
+ sectionsMutex.unlock();
+
+ for (auto& it : toRemove) {
+ EventAgregator::PushEvent(EventType::DeleteSectionRender, DeleteSectionRenderData{ it });
+ }
+
+ for (auto& it : suitableChunks) {
+ EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ it });
+ }
+ };
+
+
+ EventListener contentListener;
+ contentListener.RegisterHandler(EventType::ChunkChanged, [this](EventData eventData) {
+ auto vec = std::get<ChunkChangedData>(eventData).chunkPosition;
+ Vector playerChunk(std::floor(gs->g_PlayerX / 16), 0, std::floor(gs->g_PlayerZ / 16));
+
+ if ((playerChunk - Vector(vec.GetX(), 0, vec.GetZ())).GetMagnitude() > MaxRenderingDistance)
+ return;
+ sectionsMutex.lock();
+ auto& result = sections.find(vec);
+ if (result != sections.end()) {
+ sectionsMutex.unlock();
+ if (result->second.IsNeedResourcesPrepare())
+ result->second.PrepareResources();
+ sectionsMutex.lock();
+ }
+ else {
+ EventAgregator::PushEvent(EventType::CreateSectionRender, CreateSectionRenderData{ vec });
+ }
+ sectionsMutex.unlock();
+ });
+
+ contentListener.RegisterHandler(EventType::CreatedSectionRender, [this](EventData eventData) {
+ auto vec = std::get<CreatedSectionRenderData>(eventData).pos;
+ sectionsMutex.lock();
+ sections.find(vec)->second.PrepareResources();
+ sectionsMutex.unlock();
+ EventAgregator::PushEvent(EventType::InitalizeSectionRender, InitalizeSectionRenderData{ vec });
+ });
+
+ contentListener.RegisterHandler(EventType::PlayerPosChanged, [this,&updateAllSections](EventData eventData) {
+ auto pos = std::get<PlayerPosChangedData>(eventData).newPos;
+ updateAllSections(pos);
+ });
+
+ contentListener.RegisterHandler(EventType::UpdateSectionsRender, [this,&updateAllSections](EventData eventData) {
+ updateAllSections(Vector(gs->g_PlayerX, gs->g_PlayerY, gs->g_PlayerZ));
+ });
+
+ LoopExecutionTimeController timer(std::chrono::milliseconds(32));
+ auto timeSincePreviousUpdate = std::chrono::steady_clock::now();
+ while (isRunning) {
+ while (contentListener.IsEventsQueueIsNotEmpty())
+ contentListener.HandleEvent();
+ if (std::chrono::steady_clock::now() - timeSincePreviousUpdate > std::chrono::seconds(15)) {
+ EventAgregator::PushEvent(EventType::UpdateSectionsRender, UpdateSectionsRenderData{});
+ timeSincePreviousUpdate = std::chrono::steady_clock::now();
+ }
+ timer.Update();
+ }
+}
+
+RendererWorld::RendererWorld(GameState * ptr):gs(ptr) {
+ MaxRenderingDistance = 2;
+
+ PrepareRender();
+
+ listener.RegisterHandler(EventType::InitalizeSectionRender, [this](EventData eventData) {
+ auto data = std::get<InitalizeSectionRenderData>(eventData);
+ sectionsMutex.lock();
+ sections.find(data.pos)->second.PrepareRender();
+ sections.find(data.pos)->second.SetEnabled(true);
+ sectionsMutex.unlock();
+ });
+
+ listener.RegisterHandler(EventType::CreateSectionRender, [this](EventData eventData) {
+ auto vec = std::get<CreateSectionRenderData>(eventData).pos;
+ sectionsMutex.lock();
+ sections.insert(std::make_pair(vec, RendererSection(&gs->world, vec)));
+ sectionsMutex.unlock();
+ EventAgregator::PushEvent(EventType::CreatedSectionRender, CreatedSectionRenderData{ vec });
+ });
+
+ listener.RegisterHandler(EventType::DeleteSectionRender, [this](EventData eventData) {
+ auto vec = std::get<DeleteSectionRenderData>(eventData).pos;
+ sectionsMutex.lock();
+ sections.erase(sections.find(vec));
+ sectionsMutex.unlock();
+ });
+
+ resourceLoader = std::thread(&RendererWorld::LoadedSectionController, this);
+}
+
+RendererWorld::~RendererWorld() {
+ isRunning = false;
+ resourceLoader.join();
+ delete shader;
+}
+
+void RendererWorld::Render(RenderState & renderState) {
+ renderState.SetActiveShader(shader->Program);
+ glCheckError();
+
+ GLint projectionLoc = glGetUniformLocation(shader->Program, "projection");
+ GLint viewLoc = glGetUniformLocation(shader->Program, "view");
+ GLint windowSizeLoc = glGetUniformLocation(shader->Program, "windowSize");
+ glm::mat4 projection = glm::perspective(45.0f, (float)renderState.WindowWidth / (float)renderState.WindowHeight, 0.1f, 10000000.0f);
+ glm::mat4 view = gs->GetViewMatrix();
+ glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
+ glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
+ glUniform2f(windowSizeLoc, renderState.WindowWidth, renderState.WindowHeight);
+
+ glCheckError();
+
+ sectionsMutex.lock();
+ for (auto& it : sections)
+ it.second.Render(renderState);
+ sectionsMutex.unlock();
+
+ listener.HandleEvent();
+}
+
+void RendererWorld::PrepareResources() {
+ LOG(ERROR) << "Incorrect call";
+}
+
+void RendererWorld::PrepareRender() {
+ shader = new Shader("./shaders/face.vs", "./shaders/face.fs");
+ shader->Use();
+ glUniform1i(glGetUniformLocation(shader->Program, "textureAtlas"), 0);
+}
+
+bool RendererWorld::IsNeedResourcesPrepare() {
+ LOG(ERROR) << "Incorrect call";
+ return false;
+}
diff --git a/src/RendererWorld.hpp b/src/RendererWorld.hpp
index 83020aa..2ae4e37 100644
--- a/src/RendererWorld.hpp
+++ b/src/RendererWorld.hpp
@@ -1,12 +1,28 @@
#pragma once
#include "RendererSection.hpp"
+#include "GameState.hpp"
+#include "Shader.hpp"
-class RendererWorld {
- World* world;
+#include <glm/gtc/type_ptr.hpp>
+
+class RendererWorld: public Renderer {
+ GameState *gs;
+ std::mutex sectionsMutex;
+ std::map<Vector, RendererSection> sections;
+ EventListener listener;
+ Shader *shader;
+ std::thread resourceLoader;
+ void LoadedSectionController();
+ bool isRunning = true;
public:
- RendererWorld(World* ptr);
+ RendererWorld(GameState* ptr);
~RendererWorld();
+ void Render(RenderState& renderState) override;
+ void PrepareResources() override;
+ void PrepareRender() override;
+ bool IsNeedResourcesPrepare() override;
+ double MaxRenderingDistance;
}; \ No newline at end of file
diff --git a/src/Shader.cpp b/src/Shader.cpp
index cf43115..164da69 100644
--- a/src/Shader.cpp
+++ b/src/Shader.cpp
@@ -3,101 +3,94 @@
Shader::Shader(const GLchar *vertexPath, const GLchar *fragmentPath, const GLchar *geometryPath) {
vertex = vertexPath;
fragment = fragmentPath;
- // 1. Получаем исходный код шейдера из filePath
+
std::string vertexCode;
std::string fragmentCode;
std::string geometryCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
std::ifstream gShaderFile;
- // Удостоверимся, что ifstream объекты могут выкидывать исключения
+
vShaderFile.exceptions(std::ifstream::failbit);
fShaderFile.exceptions(std::ifstream::failbit);
gShaderFile.exceptions(std::ifstream::failbit);
- try {
- // Открываем файлы
+ try {
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
if (geometryPath != nullptr)
gShaderFile.open(geometryPath);
std::stringstream vShaderStream, fShaderStream, gShaderStream;
- // Считываем данные в потоки
+
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
if (geometryPath != nullptr)
gShaderStream << gShaderFile.rdbuf();
- // Закрываем файлы
+
vShaderFile.close();
fShaderFile.close();
if (geometryPath != nullptr)
gShaderFile.close();
- // Преобразовываем потоки в массив GLchar
+
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
if (geometryPath != nullptr)
geometryCode = gShaderStream.str();
}
catch (std::ifstream::failure e) {
- LOG(ERROR) << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ";
+ LOG(ERROR) << "Shader source not readed";
}
const GLchar *vShaderCode = vertexCode.c_str();
const GLchar *fShaderCode = fragmentCode.c_str();
const GLchar *gShaderCode = geometryCode.c_str();
- // 2. Сборка шейдеров
GLuint vertex, fragment, geometry;
GLint success;
GLchar infoLog[512];
- // Вершинный шейдер
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
- // Если есть ошибки - вывести их
+
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
- LOG(ERROR) << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog;
+ LOG(ERROR) << "Vertex shader compilation failed: " << infoLog;
};
- // Вершинный шейдер
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
- // Если есть ошибки - вывести их
+
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
- LOG(ERROR) << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog;
+ LOG(ERROR) << "Fragment shader compilation failed: " << infoLog;
};
if (geometryPath != nullptr) {
geometry = glCreateShader(GL_GEOMETRY_SHADER);
glShaderSource(geometry, 1, &gShaderCode, NULL);
glCompileShader(geometry);
- // Если есть ошибки - вывести их
+
glGetShaderiv(geometry, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(geometry, 512, NULL, infoLog);
- LOG(ERROR) << "ERROR::SHADER::GEOMETRY::COMPILATION_FAILED\n" << infoLog;
+ LOG(ERROR) << "Geometry shader compilation failed: " << infoLog;
};
}
- // Шейдерная программа
this->Program = glCreateProgram();
glAttachShader(this->Program, vertex);
glAttachShader(this->Program, fragment);
if (geometryPath != nullptr)
glAttachShader(this->Program, geometry);
glLinkProgram(this->Program);
- //Если есть ошибки - вывести их
glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
- LOG(FATAL) << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog;
+ LOG(FATAL) << "Shader program not linked: " << infoLog;
}
- // Удаляем шейдеры, поскольку они уже в программу и нам больше не нужны.
glDeleteShader(vertex);
glDeleteShader(fragment);
}
diff --git a/src/Stream.cpp b/src/Stream.cpp
index 54b1e1b..3931a40 100644
--- a/src/Stream.cpp
+++ b/src/Stream.cpp
@@ -70,7 +70,7 @@ std::string StreamInput::ReadString() {
ReadData(buff, strLength);
buff[strLength] = 0;
std::string str((char *) buff);
- delete buff;
+ delete[] buff;
return str;
}
@@ -161,7 +161,7 @@ std::vector<unsigned char> StreamInput::ReadByteArray(size_t arrLength) {
unsigned char *buffer = new unsigned char[arrLength];
ReadData(buffer, arrLength);
std::vector<unsigned char> ret(buffer, buffer + arrLength);
- delete buffer;
+ delete[] buffer;
return ret;
}
@@ -311,7 +311,7 @@ StreamBuffer::StreamBuffer(size_t bufferLen) {
}
StreamBuffer::~StreamBuffer() {
- delete buffer;
+ delete[] buffer;
}
std::vector<unsigned char> StreamBuffer::GetBuffer() {
diff --git a/src/ThreadGame.cpp b/src/ThreadGame.cpp
index 03c2c14..7bb3678 100644
--- a/src/ThreadGame.cpp
+++ b/src/ThreadGame.cpp
@@ -13,22 +13,83 @@ void ThreadGame::Execute() {
EventListener listener;
- listener.RegisterHandler(EventType::GlobalAppState, [this](EventData eventData) {
- auto data = std::get<GlobalAppStateData>(eventData);
- state = data.state;
- });
+ listener.RegisterHandler(EventType::Exit, [this] (EventData eventData) {
+ isRunning = false;
+ });
listener.RegisterHandler(EventType::ConnectionSuccessfull, [this](EventData eventData) {
auto data = std::get<ConnectionSuccessfullData>(eventData);
gs = new GameState(data.ptr);
});
+ listener.RegisterHandler(EventType::Disconnected, [this](EventData eventData) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
+ delete gs;
+ gs = nullptr;
+ });
+
+ listener.RegisterHandler(EventType::KeyPressed, [this](EventData eventData) {
+ if (!gs)
+ return;
+ switch (std::get<KeyPressedData>(eventData).key) {
+ case sf::Keyboard::W:
+ isMoving[GameState::FORWARD] = true;
+ break;
+ case sf::Keyboard::A:
+ isMoving[GameState::LEFT] = true;
+ break;
+ case sf::Keyboard::S:
+ isMoving[GameState::BACKWARD] = true;
+ break;
+ case sf::Keyboard::D:
+ isMoving[GameState::RIGHT] = true;
+ break;
+ }
+ });
+
+ listener.RegisterHandler(EventType::KeyReleased, [this](EventData eventData) {
+ if (!gs)
+ return;
+ switch (std::get<KeyReleasedData>(eventData).key) {
+ case sf::Keyboard::W:
+ isMoving[GameState::FORWARD] = false;
+ break;
+ case sf::Keyboard::A:
+ isMoving[GameState::LEFT] = false;
+ break;
+ case sf::Keyboard::S:
+ isMoving[GameState::BACKWARD] = false;
+ break;
+ case sf::Keyboard::D:
+ isMoving[GameState::RIGHT] = false;
+ break;
+ }
+ });
+
+ listener.RegisterHandler(EventType::MouseMoved, [this](EventData eventData) {
+ if (!gs)
+ return;
+ auto data = std::get<MouseMovedData>(eventData);
+ gs->HandleRotation(data.x, data.y);
+ });
+
LoopExecutionTimeController timer(std::chrono::milliseconds(int(1.0f / 60.0f * 1000.0f)));
- while (state != GlobalState::Exiting) {
+ while (isRunning) {
+ if (gs != nullptr)
+ gs->Update(timer.GetDeltaS());
listener.HandleEvent();
- if (gs != nullptr)
- gs->Update(timer.GetDeltaMs());
+ if (gs != nullptr) {
+ gs->UpdatePacket();
+ if (isMoving[GameState::FORWARD])
+ gs->HandleMovement(GameState::FORWARD, timer.GetDeltaS());
+ if (isMoving[GameState::BACKWARD])
+ gs->HandleMovement(GameState::BACKWARD, timer.GetDeltaS());
+ if (isMoving[GameState::LEFT])
+ gs->HandleMovement(GameState::LEFT, timer.GetDeltaS());
+ if (isMoving[GameState::RIGHT])
+ gs->HandleMovement(GameState::RIGHT, timer.GetDeltaS());
+ }
timer.Update();
}
delete gs;
diff --git a/src/ThreadGame.hpp b/src/ThreadGame.hpp
index 81d135f..1254183 100644
--- a/src/ThreadGame.hpp
+++ b/src/ThreadGame.hpp
@@ -6,7 +6,8 @@
class ThreadGame: Thread {
GameState *gs = nullptr;
- GlobalState state = GlobalState::InitialLoading;
+ bool isRunning = true;
+ bool isMoving[4] = { 0,0,0,0 };
public:
ThreadGame();
~ThreadGame();
diff --git a/src/ThreadNetwork.cpp b/src/ThreadNetwork.cpp
index 51c8989..f734c0c 100644
--- a/src/ThreadNetwork.cpp
+++ b/src/ThreadNetwork.cpp
@@ -4,18 +4,15 @@ ThreadNetwork::ThreadNetwork() {
}
-ThreadNetwork::~ThreadNetwork() {
- delete nc;
+ThreadNetwork::~ThreadNetwork() {
}
void ThreadNetwork::Execute() {
- state = GlobalState::InitialLoading;
EventListener listener;
- listener.RegisterHandler(EventType::GlobalAppState, [this](EventData eventData) {
- auto data = std::get<GlobalAppStateData>(eventData);
- state = data.state;
- });
+ listener.RegisterHandler(EventType::Exit, [this] (EventData eventData) {
+ isRunning = false;
+ });
listener.RegisterHandler(EventType::ConnectToServer, [this](EventData eventData) {
auto data = std::get<ConnectToServerData>(eventData);
@@ -25,8 +22,8 @@ void ThreadNetwork::Execute() {
LOG(ERROR) << "Already connected";
return;
}
- SetGlobalState(GlobalState::Connecting);
LOG(INFO) << "Connecting to server";
+ EventAgregator::PushEvent(EventType::Connecting, ConnectingData{});
try {
nc = new NetworkClient(data.address, data.port, "HelloOne");
} catch (std::exception &e) {
@@ -38,11 +35,24 @@ void ThreadNetwork::Execute() {
EventAgregator::PushEvent(EventType::ConnectionSuccessfull, ConnectionSuccessfullData{nc});
});
- listener.RegisterHandler(EventType::RequestNetworkClient, [this](EventData eventData) {
- EventAgregator::PushEvent(EventType::RegisterNetworkClient, RegisterNetworkClientData{nc});
- });
-
- while (state != GlobalState::Exiting) {
+ listener.RegisterHandler(EventType::Disconnect, [this](EventData eventData) {
+ auto data = std::get<DisconnectData>(eventData);
+ EventAgregator::PushEvent(EventType::Disconnected, DisconnectedData{ data.reason });
+ LOG(INFO) << "Disconnected: " << data.reason;
+ delete nc;
+ nc = nullptr;
+ });
+
+ listener.RegisterHandler(EventType::NetworkClientException, [this](EventData eventData) {
+ auto data = std::get<NetworkClientExceptionData>(eventData);
+ EventAgregator::PushEvent(EventType::Disconnect, DisconnectData{ data.what });
+ });
+
+ LoopExecutionTimeController timer(std::chrono::milliseconds(16));
+ while (isRunning) {
listener.HandleEvent();
+
+ timer.Update();
}
+ delete nc;
} \ No newline at end of file
diff --git a/src/ThreadNetwork.hpp b/src/ThreadNetwork.hpp
index a0917cd..60df0d0 100644
--- a/src/ThreadNetwork.hpp
+++ b/src/ThreadNetwork.hpp
@@ -6,7 +6,7 @@
class ThreadNetwork : Thread {
NetworkClient *nc = nullptr;
- GlobalState state;
+ bool isRunning = true;
public:
ThreadNetwork();
~ThreadNetwork();
diff --git a/src/Utility.cpp b/src/Utility.cpp
index 9fecc08..b4e1d99 100644
--- a/src/Utility.cpp
+++ b/src/Utility.cpp
@@ -71,3 +71,11 @@ LoopExecutionTimeController::duration LoopExecutionTimeController::GetDelta() {
//std::cerr<<duration(now-previousUpdate).count()<<std::endl;
return duration(now-previousUpdate);
}
+
+double LoopExecutionTimeController::GetDeltaS()
+{
+ auto now = clock::now();
+ return std::chrono::duration<double, std::ratio<1, 1>>(now - previousUpdate).count();
+}
+
+
diff --git a/src/Utility.hpp b/src/Utility.hpp
index 52d6016..0ae3540 100644
--- a/src/Utility.hpp
+++ b/src/Utility.hpp
@@ -49,4 +49,6 @@ public:
double GetDeltaMs();
duration GetDelta();
+
+ double GetDeltaS();
};
diff --git a/src/World.cpp b/src/World.cpp
index 487f4ba..723b006 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -1,4 +1,5 @@
#include "World.hpp"
+#include "Event.hpp"
void World::ParseChunkData(std::shared_ptr<PacketChunkData> packet) {
StreamBuffer chunkData(packet->Data.data(), packet->Data.size());
@@ -17,6 +18,8 @@ void World::ParseChunkData(std::shared_ptr<PacketChunkData> packet) {
swap(it->second, section);
}
sectionMutexes[chunkPosition].unlock();
+
+ EventAgregator::PushEvent(EventType::ChunkChanged, ChunkChangedData{ chunkPosition });
}
}
}
diff --git a/src/World.hpp b/src/World.hpp
index 52493a7..805084c 100644
--- a/src/World.hpp
+++ b/src/World.hpp
@@ -17,9 +17,7 @@ class World {
int dimension = 0;
Section ParseSection(StreamInput *data, Vector position);
-
- World(const World &other);
- World &operator=(const World &other);
+
public:
World();