summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Game.cpp54
-rw-r--r--src/GameState.cpp39
-rw-r--r--src/GameState.hpp7
-rw-r--r--src/Network.cpp3
-rw-r--r--src/NetworkClient.cpp20
-rw-r--r--src/Packet.hpp61
-rw-r--r--src/Section.cpp8
-rw-r--r--src/Stream.cpp9
-rw-r--r--src/Stream.hpp3
-rw-r--r--src/World.cpp7
10 files changed, 178 insertions, 33 deletions
diff --git a/src/Game.cpp b/src/Game.cpp
index c69ff5d..f0266d4 100644
--- a/src/Game.cpp
+++ b/src/Game.cpp
@@ -18,35 +18,61 @@ std::unique_ptr<Render> render;
std::unique_ptr<LoopExecutionTimeController> timer;
EventListener listener;
-void InitEvents() {
- /*
- * Network Events
- */
+std::thread connThread;
+std::unique_ptr<NetworkClient> connNc;
+std::unique_ptr<GameState> connGs;
+
+void ConnectionThreadExec() {
+ EventListener connListener;
- listener.RegisterHandler("ConnectToServer", [](const Event & eventData) {
+ bool connRun = true;
+
+ connListener.RegisterHandler("ConnectToServer", [](const Event& eventData) {
auto data = eventData.get <std::tuple<std::string, unsigned short, std::string>>(); //address,port,username
if (std::get<0>(data) == "" || std::get<1>(data) == 0)
LOG(FATAL) << "NOT VALID CONNECT-TO-SERVER EVENT";
- if (nc != nullptr) {
+ if (connNc != nullptr) {
LOG(ERROR) << "Already connected";
return;
}
LOG(INFO) << "Connecting to server at address " + std::get<0>(data) + ":" + std::to_string(std::get<1>(data)) + " as " + std::get<2>(data);
- PUSH_EVENT("Connecting",0);
- gs = std::make_unique<GameState>();
+ PUSH_EVENT("Connecting", 0);
+ connGs = std::make_unique<GameState>();
try {
- nc = std::make_unique<NetworkClient>(std::get<0>(data),
+ connNc = std::make_unique<NetworkClient>(std::get<0>(data),
std::get<1>(data),
std::get<2>(data));
- } catch (std::exception &e) {
+ }
+ catch (std::exception& e) {
LOG(WARNING) << "Connection failed";
PUSH_EVENT("ConnectionFailed", std::string(e.what()));
- gs.reset();
+ connGs.reset();
return;
}
LOG(INFO) << "Connected to server";
PUSH_EVENT("ConnectionSuccessfull", 0);
- });
+ });
+
+ connListener.RegisterHandler("Exit", [&](const Event&) {
+ connRun = false;
+ });
+
+ LoopExecutionTimeController timer(std::chrono::milliseconds(50));
+ while (connRun) {
+ connListener.HandleAllEvents();
+ timer.Update();
+ }
+}
+
+void InitEvents() {
+ /*
+ * Network Events
+ */
+
+ listener.RegisterHandler("ConnectionSuccessfull", [](const Event&) {
+ nc = std::move(connNc);
+ gs = std::move(connGs);
+ });
listener.RegisterHandler("Disconnect", [](const Event& eventData) {
auto data = eventData.get<std::string>();
@@ -186,6 +212,8 @@ void RunGame() {
render = std::make_unique<Render>(900, 480, "AltCraft");
+ connThread = std::thread(ConnectionThreadExec);
+
SetState(State::MainMenu);
while (isRunning) {
@@ -212,6 +240,8 @@ void RunGame() {
}
render.reset();
+
+ connThread.join();
}
State GetState() {
diff --git a/src/GameState.cpp b/src/GameState.cpp
index fdb453f..3d1714b 100644
--- a/src/GameState.cpp
+++ b/src/GameState.cpp
@@ -9,6 +9,22 @@
void GameState::Update(double deltaTime) {
OPTICK_EVENT();
+
+ if (!gameStatus.isGameStarted) {
+ if (!receivedEnoughChunks) {
+ receivedEnoughChunks = world.GetSectionsList().size() >= 49;
+ }
+
+ if (receivedJoinGame && receivedEnoughChunks && receivedFirstPlayerPosAndLook) {
+ gameStatus.isGameStarted = true;
+ LOG(INFO) << "Game is started";
+ PUSH_EVENT("RemoveLoadingScreen", 0);
+
+ auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0);
+ PUSH_EVENT("SendPacket", std::static_pointer_cast<Packet>(packetPerformRespawn));
+ }
+ }
+
if (!gameStatus.isGameStarted)
return;
@@ -268,6 +284,18 @@ void GameState::UpdatePacket(std::shared_ptr<Packet> ptr) {
LOG(INFO) << "Gamemode is " << gameStatus.gamemode << ", Difficulty is " << (int)gameStatus.difficulty
<< ", Level Type is " << gameStatus.levelType;
PUSH_EVENT("PlayerConnected", 0);
+
+ receivedJoinGame = true;
+
+ auto packetSettings = std::make_shared<PacketClientSettings>("en_us", 0x14, 0, true, 0x7F, 1);
+ PUSH_EVENT("SendPacket", std::static_pointer_cast<Packet>(packetSettings));
+
+ std::string brandStr("\x08""AltCraft");
+ std::vector<unsigned char> brandData;
+ std::copy(brandStr.begin(), brandStr.end(), std::back_inserter(brandData));
+ auto packetPluginBrand = std::make_shared<PacketPluginMessageSB>("MC|Brand", brandData);
+ PUSH_EVENT("SendPacket", std::static_pointer_cast<Packet>(packetPluginBrand));
+
break;
}
@@ -354,18 +382,11 @@ void GameState::UpdatePacket(std::shared_ptr<Packet> ptr) {
PUSH_EVENT("PlayerPosChanged", player->pos);
LOG(INFO) << "PlayerPos is " << player->pos << "\t\tAngle: " << player->yaw << "," << player->pitch;;
- if (!gameStatus.isGameStarted) {
- LOG(INFO) << "Game is started";
- PUSH_EVENT("RemoveLoadingScreen", 0);
- }
-
- gameStatus.isGameStarted = true;
+ receivedFirstPlayerPosAndLook = true;
auto packetResponse = std::make_shared<PacketTeleportConfirm>(packet->TeleportId);
- auto packetPerformRespawn = std::make_shared<PacketClientStatus>(0);
-
PUSH_EVENT("SendPacket", std::static_pointer_cast<Packet>(packetResponse));
- PUSH_EVENT("SendPacket", std::static_pointer_cast<Packet>(packetPerformRespawn));
+
break;
}
diff --git a/src/GameState.hpp b/src/GameState.hpp
index 5489ac6..0ca858f 100644
--- a/src/GameState.hpp
+++ b/src/GameState.hpp
@@ -68,6 +68,13 @@ class GameState {
Window playerInventory;
std::vector<Window> openedWindows;
+
+ bool receivedJoinGame = false;
+
+ bool receivedEnoughChunks = false;
+
+ bool receivedFirstPlayerPosAndLook = false;
+
public:
void Update(double deltaTime);
diff --git a/src/Network.cpp b/src/Network.cpp
index bb92e7f..4280b50 100644
--- a/src/Network.cpp
+++ b/src/Network.cpp
@@ -98,7 +98,8 @@ void Network::SendPacket(Packet &packet, int compressionThreshold) {
stream->WriteVarInt(packetSize.GetCountedSize());
stream->WriteVarInt(packet.GetPacketId());
packet.ToStream(stream.get());
- }
+ }
+ stream->Flush();
}
std::shared_ptr<Packet> Network::ReceivePacketByPacketId(int packetId, ConnectionState state, StreamInput &stream) {
diff --git a/src/NetworkClient.cpp b/src/NetworkClient.cpp
index 6273937..ee79fb9 100644
--- a/src/NetworkClient.cpp
+++ b/src/NetworkClient.cpp
@@ -24,17 +24,29 @@ NetworkClient::NetworkClient(std::string address, unsigned short port, std::stri
auto packet = network->ReceivePacket(Login);
- while (!packet)
- packet = network->ReceivePacket(Login);
+ for (int i = 0; i < 10 && !packet; i++)
+ packet = network->ReceivePacket(Login);
+ if (!packet)
+ throw std::runtime_error("Server not answered after LoginStart");
if (packet->GetPacketId() == PacketNameLoginCB::SetCompression) {
auto compPacket = std::static_pointer_cast<PacketSetCompression>(packet);
LOG(INFO) << "Compression threshold: " << compPacket->Threshold;
compressionThreshold = compPacket->Threshold;
packet.reset();
- while (!packet)
- packet = network->ReceivePacket(Login, compressionThreshold >= 0);
+ for (int i = 0; i < 10 && !packet; i++)
+ packet = network->ReceivePacket(Login, compressionThreshold >= 0);
+ if (!packet)
+ throw std::runtime_error("Server not answered after SetCompression");
}
+ else if (packet->GetPacketId() == PacketNameLoginCB::Disconnect) {
+ auto disconnectPacket = std::static_pointer_cast<PacketDisconnect>(packet);
+ LOG(INFO) << "Server not allowed connection: " << disconnectPacket->Reason;
+ throw std::runtime_error(disconnectPacket->Reason);
+ }
+ else if (packet->GetPacketId() != PacketNameLoginCB::LoginSuccess) {
+ throw std::runtime_error("Unexpected packet type: " + std::to_string(packet->GetPacketId()));
+ }
auto response = std::static_pointer_cast<PacketLoginSuccess>(packet);
diff --git a/src/Packet.hpp b/src/Packet.hpp
index cca01ec..ccc486f 100644
--- a/src/Packet.hpp
+++ b/src/Packet.hpp
@@ -1169,3 +1169,64 @@ struct PacketRespawn : Packet {
unsigned char Gamemode;
std::string LevelType;
};
+
+struct PacketPluginMessageSB : Packet {
+ void ToStream(StreamOutput* stream) override {
+ stream->WriteString(Channel);
+ stream->WriteByteArray(Data);
+ }
+
+ void FromStream(StreamInput* stream) override {
+
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlaySB::PluginMessageSB;
+ }
+
+ PacketPluginMessageSB(const std::string& channel, const std::vector<unsigned char> data) : Channel(channel), Data(data) {}
+
+ std::string Channel;
+ std::vector<unsigned char> Data;
+};
+
+struct PacketClientSettings : Packet {
+ void ToStream(StreamOutput* stream) override {
+ stream->WriteString(Locale);
+ stream->WriteByte(ViewDistance);
+ stream->WriteVarInt(ChatMode);
+ stream->WriteBool(ChatColors);
+ stream->WriteUByte(DisplayedSkinParts);
+ stream->WriteVarInt(MainHand);
+ }
+
+ void FromStream(StreamInput* stream) override {
+
+ }
+
+ int GetPacketId() override {
+ return PacketNamePlaySB::ClientSettings;
+ }
+
+ PacketClientSettings(
+ const std::string locale,
+ unsigned char viewDistance,
+ int chatMode,
+ bool chatColors,
+ unsigned char displayedSkinParts,
+ int mainHand) :
+ Locale(locale),
+ ViewDistance(viewDistance),
+ ChatMode(chatMode),
+ ChatColors(chatColors),
+ DisplayedSkinParts(displayedSkinParts),
+ MainHand(mainHand) {}
+
+ std::string Locale;
+ unsigned char ViewDistance;
+ int ChatMode;
+ bool ChatColors;
+ unsigned char DisplayedSkinParts;
+ int MainHand;
+};
+
diff --git a/src/Section.cpp b/src/Section.cpp
index 4a15c58..1d9c203 100644
--- a/src/Section.cpp
+++ b/src/Section.cpp
@@ -61,16 +61,16 @@ BlockId Section::GetBlockId(Vector pos) const {
return iter->second;
}
- int value;
+ unsigned int value;
- unsigned char individualValueMask = ((1 << bitsPerBlock) - 1);
+ unsigned int individualValueMask = ((1 << (unsigned int)bitsPerBlock) - 1);
int blockNumber = (((pos.y * 16) + pos.z) * 16) + pos.x;
int startLong = (blockNumber * bitsPerBlock) / 64;
int startOffset = (blockNumber * bitsPerBlock) % 64;
int endLong = ((blockNumber + 1) * bitsPerBlock - 1) / 64;
- unsigned char t;
+ unsigned int t;
if (startLong == endLong) {
t = (block[startLong] >> startOffset);
@@ -85,7 +85,7 @@ BlockId Section::GetBlockId(Vector pos) const {
if (t >= palette.size()) {
//LOG(ERROR) << "Out of palette: " << t;
- value = 0;
+ value = t;
}
else
value = palette[t];
diff --git a/src/Stream.cpp b/src/Stream.cpp
index efe37d2..5c99724 100644
--- a/src/Stream.cpp
+++ b/src/Stream.cpp
@@ -360,9 +360,14 @@ void StreamSocket::ReadData(unsigned char *buffPtr, size_t buffLen) {
}
void StreamSocket::WriteData(unsigned char *buffPtr, size_t buffLen) {
- socket->Write(buffPtr, buffLen);
+ std::copy(buffPtr, buffPtr + buffLen, std::back_inserter(buffer));
}
StreamSocket::StreamSocket(Socket *socketPtr) : socket(socketPtr) {
-} \ No newline at end of file
+}
+
+void StreamSocket::Flush() {
+ socket->Write(buffer.data(), buffer.size());
+ buffer.clear();
+}
diff --git a/src/Stream.hpp b/src/Stream.hpp
index a7c161b..9b6e5ff 100644
--- a/src/Stream.hpp
+++ b/src/Stream.hpp
@@ -100,9 +100,12 @@ public:
class StreamSocket : public StreamInput, public StreamOutput {
Socket *socket;
+ std::vector<unsigned char> buffer;
void ReadData(unsigned char *buffPtr, size_t buffLen) override;
void WriteData(unsigned char *buffPtr, size_t buffLen) override;
public:
StreamSocket(Socket *socketPtr);
~StreamSocket() = default;
+
+ void Flush();
}; \ No newline at end of file
diff --git a/src/World.cpp b/src/World.cpp
index d767871..c3246dc 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -378,7 +378,12 @@ void World::SetBlockId(Vector pos, BlockId block) {
std::floor(pos.y / 16.0),
std::floor(pos.z / 16.0));
Vector blockPos = pos - (sectionPos * 16);
- auto section = std::make_shared<Section>(*GetSectionPtr(sectionPos));
+ const Section* sectionPtr = GetSectionPtr(sectionPos);
+ if (!sectionPtr) {
+ LOG(ERROR) << "Updating unloaded chunk " << sectionPos;
+ return;
+ }
+ auto section = std::make_shared<Section>(*sectionPtr);
section->SetBlockId(blockPos, block);
sections[sectionPos] = section;
PUSH_EVENT("ChunkChanged",sectionPos);