about summary refs log tree commit diff stats
path: root/ap_state.cpp
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2023-05-02 15:21:29 -0400
committerStar Rauchenberger <fefferburbia@gmail.com>2023-05-02 15:21:29 -0400
commit116ba412079ddf647d19a54d09eb61e67a2f9aac (patch)
tree07934e4fdd0723f1cd803cd37832c0f2302e3c53 /ap_state.cpp
parent22014b967d0d9651b72bffbe02aba75dc98180a4 (diff)
downloadlingo-ap-tracker-116ba412079ddf647d19a54d09eb61e67a2f9aac.tar.gz
lingo-ap-tracker-116ba412079ddf647d19a54d09eb61e67a2f9aac.tar.bz2
lingo-ap-tracker-116ba412079ddf647d19a54d09eb61e67a2f9aac.zip
Tracker connects to AP now
Diffstat (limited to 'ap_state.cpp')
-rw-r--r--ap_state.cpp162
1 files changed, 162 insertions, 0 deletions
diff --git a/ap_state.cpp b/ap_state.cpp new file mode 100644 index 0000000..d85fde5 --- /dev/null +++ b/ap_state.cpp
@@ -0,0 +1,162 @@
1#include "ap_state.h"
2
3#include <hkutil/string.h>
4
5#include <apuuid.hpp>
6#include <chrono>
7#include <exception>
8#include <list>
9#include <thread>
10
11constexpr int AP_MAJOR = 0;
12constexpr int AP_MINOR = 4;
13constexpr int AP_REVISION = 0;
14
15constexpr int ITEM_HANDLING = 7; // <- all
16
17APState::APState() {
18 std::thread([this]() {
19 for (;;) {
20 {
21 std::lock_guard client_guard(client_mutex_);
22 if (apclient_) {
23 apclient_->poll();
24 }
25 }
26
27 std::this_thread::sleep_for(std::chrono::milliseconds(100));
28 }
29 }).detach();
30}
31
32void APState::Connect(std::string server, std::string player,
33 std::string password) {
34 tracker_frame_->SetStatusMessage("Connecting to Archipelago server....");
35
36 {
37 std::lock_guard client_guard(client_mutex_);
38
39 if (apclient_) {
40 apclient_->reset();
41 }
42
43 apclient_ = std::make_unique<APClient>(ap_get_uuid(""), "Lingo", server);
44 }
45
46 inventory_.clear();
47 checked_locations_.clear();
48
49 bool connected = false;
50 bool has_connection_result = false;
51
52 apclient_->set_room_info_handler([&]() {
53 tracker_frame_->SetStatusMessage(
54 "Connected to Archipelago server. Authenticating...");
55
56 apclient_->ConnectSlot(player, password, ITEM_HANDLING, {"Tracker"},
57 {AP_MAJOR, AP_MINOR, AP_REVISION});
58 });
59
60 apclient_->set_location_checked_handler(
61 [&](const std::list<int64_t>& locations) {
62 for (const int64_t location_id : locations) {
63 checked_locations_.insert(location_id);
64 std::cout << "Location: " << location_id << std::endl;
65 }
66
67 tracker_frame_->Refresh();
68 });
69
70 apclient_->set_slot_disconnected_handler([&]() {
71 tracker_frame_->SetStatusMessage("Disconnected from Archipelago.");
72 });
73
74 apclient_->set_socket_disconnected_handler([&]() {
75 tracker_frame_->SetStatusMessage("Disconnected from Archipelago.");
76 });
77
78 apclient_->set_items_received_handler(
79 [&](const std::list<APClient::NetworkItem>& items) {
80 for (const APClient::NetworkItem& item : items) {
81 // TODO: Progressive items.
82
83 inventory_.insert(item.item);
84 std::cout << "Item: " << item.item << std::endl;
85 }
86
87 tracker_frame_->Refresh();
88 });
89
90 apclient_->set_slot_connected_handler([&](const nlohmann::json& slot_data) {
91 tracker_frame_->SetStatusMessage("Connected to Archipelago!");
92
93 connected = true;
94 has_connection_result = true;
95 });
96
97 apclient_->set_slot_refused_handler(
98 [&](const std::list<std::string>& errors) {
99 connected = false;
100 has_connection_result = true;
101
102 tracker_frame_->SetStatusMessage("Disconnected from Archipelago.");
103
104 std::vector<std::string> error_messages;
105 error_messages.push_back("Could not connect to Archipelago.");
106
107 for (const std::string& error : errors) {
108 if (error == "InvalidSlot") {
109 error_messages.push_back("Invalid player name.");
110 } else if (error == "InvalidGame") {
111 error_messages.push_back(
112 "The specified player is not playing Lingo.");
113 } else if (error == "IncompatibleVersion") {
114 error_messages.push_back(
115 "The Archipelago server is not the correct version for this "
116 "client.");
117 } else if (error == "InvalidPassword") {
118 error_messages.push_back("Incorrect password.");
119 } else if (error == "InvalidItemsHandling") {
120 error_messages.push_back(
121 "Invalid item handling flag. This is a bug with the tracker. "
122 "Please report it to the lingo-ap-tracker GitHub.");
123 } else {
124 error_messages.push_back("Unknown error.");
125 }
126 }
127
128 std::string full_message = hatkirby::implode(error_messages, " ");
129
130 wxMessageBox(full_message, "Connection failed", wxOK | wxICON_ERROR);
131 });
132
133 client_active_ = true;
134
135 int timeout = 5000; // 5 seconds
136 int interval = 100;
137 int remaining_loops = timeout / interval;
138 while (!has_connection_result) {
139 if (interval == 0) {
140 connected = false;
141 has_connection_result = true;
142
143 tracker_frame_->SetStatusMessage("Disconnected from Archipelago.");
144
145 wxMessageBox("Timeout while connecting to Archipelago server.",
146 "Connection failed", wxOK | wxICON_ERROR);
147 }
148
149 std::this_thread::sleep_for(std::chrono::milliseconds(100));
150
151 interval--;
152 }
153
154 if (!connected) {
155 client_active_ = false;
156 }
157}
158
159APState& GetAPState() {
160 static APState* instance = new APState();
161 return *instance;
162}