mirror of
				https://github.com/DarkflameUniverse/DarkflameServer.git
				synced 2025-10-31 12:41:55 +00:00 
			
		
		
		
	cleanup and make the web routes cleaner
This commit is contained in:
		| @@ -3,6 +3,7 @@ set(DCHATSERVER_SOURCES | ||||
| 	"ChatPacketHandler.cpp" | ||||
| 	"PlayerContainer.cpp" | ||||
| 	"ChatWebAPI.cpp" | ||||
| 	"JSONUtils.cpp" | ||||
| ) | ||||
|  | ||||
| add_executable(ChatServer "ChatServer.cpp") | ||||
|   | ||||
| @@ -298,12 +298,11 @@ void HandlePacket(Packet* packet) { | ||||
| 	case MessageType::Chat::LOGIN_SESSION_NOTIFY: | ||||
| 		Game::playerContainer.InsertPlayer(packet); | ||||
| 		break; | ||||
| 	case MessageType::Chat::GM_ANNOUNCE: { | ||||
| 	case MessageType::Chat::GM_ANNOUNCE: | ||||
| 		// we just forward this packet to every connected server | ||||
| 		inStream.ResetReadPointer(); | ||||
| 		Game::server->Send(inStream, packet->systemAddress, true); // send to everyone except origin | ||||
| 	} | ||||
| 									   break; | ||||
| 		break; | ||||
| 	case MessageType::Chat::UNEXPECTED_DISCONNECT: | ||||
| 		Game::playerContainer.ScheduleRemovePlayer(packet); | ||||
| 		break; | ||||
|   | ||||
| @@ -9,8 +9,13 @@ | ||||
| #include "dConfig.h" | ||||
| #include "PlayerContainer.h" | ||||
| #include "GeneralUtils.h" | ||||
| #include "JSONUtils.h" | ||||
| #include "eHTTPMethod.h" | ||||
| #include "eHTTPStatusCode.h" | ||||
| #include "magic_enum.hpp" | ||||
| #include "ChatPackets.h" | ||||
|  | ||||
| #include "json.hpp" | ||||
| #include "StringifiedEnum.h" | ||||
|  | ||||
| using json = nlohmann::json; | ||||
|  | ||||
| @@ -22,75 +27,148 @@ namespace { | ||||
| 	const char* json_content_type = "Content-Type: application/json\r\n"; | ||||
| } | ||||
|  | ||||
| struct HttpReply { | ||||
| 	uint32_t status = 404; | ||||
| struct HTTPReply { | ||||
| 	eHTTPStatusCode status = eHTTPStatusCode::NOT_FOUND; | ||||
| 	std::string message = "{\"error\":\"Not Found\"}"; | ||||
| }; | ||||
|  | ||||
| void HandleRequests(mg_connection* connection, int request, void* request_data) { | ||||
| 	if (request == MG_EV_HTTP_MSG) { | ||||
| 		HttpReply reply; | ||||
| 		const mg_http_message* const http_msg = static_cast<mg_http_message*>(request_data); | ||||
| 		if (!http_msg) { | ||||
| 			reply.status = 400; | ||||
| 			reply.message = "{\"error\":\"Invalid Request\"}"; | ||||
| 		} else { | ||||
| 			// Handle Post requests | ||||
| 			if (mg_strcmp(http_msg->method, mg_str("POST")) == 0) { | ||||
| 				auto data = GeneralUtils::TryParse<json>(http_msg->body.buf); | ||||
| 				if (!data) { | ||||
| 					reply.status = 400; | ||||
| 					reply.message = "{\"error\":\"Invalid JSON\"}"; | ||||
| 				} else if (mg_match(http_msg->uri, mg_str((root_path + "announce").c_str()), NULL)) { | ||||
| 					auto& jsonBuffer = data.value(); | ||||
| 					// handle announcements | ||||
| bool CheckValidJSON(std::optional<json> data, HTTPReply& reply) { | ||||
| 	if (!data) { | ||||
| 		reply.status = eHTTPStatusCode::BAD_REQUEST; | ||||
| 		reply.message = "{\"error\":\"Invalid JSON\"}"; | ||||
| 		return false; | ||||
| 	} | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| 					if (!jsonBuffer.contains("title")) { | ||||
| 						reply.status = 400; | ||||
| 						reply.message = "{\"error\":\"Missing paramater: title\"}"; | ||||
| 					} else if (!jsonBuffer.contains("message")) { | ||||
| 						reply.status = 400; | ||||
| 						reply.message = "{\"error\":\"Missing paramater: message\"}"; | ||||
| 					} else { | ||||
| 						std::string title = jsonBuffer["title"]; | ||||
| 						std::string message = jsonBuffer["message"]; | ||||
| void HandlePlayersRequest(HTTPReply& reply) { | ||||
| 	const json data = Game::playerContainer; | ||||
| 	reply.status = data.empty() ? eHTTPStatusCode::NO_CONTENT : eHTTPStatusCode::OK; | ||||
| 	reply.message = data.empty() ? "{\"error\":\"No Players Online\"}" : data.dump(); | ||||
| } | ||||
|  | ||||
| 						// build and send the packet to all world servers | ||||
| 						CBITSTREAM; | ||||
| 						BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::GM_ANNOUNCE); | ||||
| 						bitStream.Write<uint32_t>(title.size()); | ||||
| 						bitStream.Write(title); | ||||
| 						bitStream.Write<uint32_t>(message.size()); | ||||
| 						bitStream.Write(message); | ||||
| 						SEND_PACKET_BROADCAST; | ||||
| void HandleTeamsRequest(HTTPReply& reply) { | ||||
| 	const json data = Game::playerContainer.GetTeamContainer(); | ||||
| 	reply.status = data.empty() ? eHTTPStatusCode::NO_CONTENT : eHTTPStatusCode::OK; | ||||
| 	reply.message = data.empty() ? "{\"error\":\"No Teams Online\"}" : data.dump(); | ||||
| } | ||||
|  | ||||
| 						reply.status = 200; | ||||
| 						reply.message = "{\"status\":\"Announcement Sent\"}"; | ||||
| 					} | ||||
| 				} | ||||
| 				// Handle GET Requests | ||||
| 			} else if (mg_strcmp(http_msg->method, mg_str("GET")) == 0) { | ||||
| 				// Get All Online players | ||||
| 				if (mg_match(http_msg->uri, mg_str((root_path + "players").c_str()), NULL)) { | ||||
| 					const json data = Game::playerContainer; | ||||
| void HandleInvalidRoute(HTTPReply& reply) { | ||||
| 	reply.status = eHTTPStatusCode::NOT_FOUND; | ||||
| 	reply.message = "{\"error\":\"Invalid Route\"}"; | ||||
| } | ||||
|  | ||||
| 					reply.status = data.empty() ? 204 : 200; | ||||
| 					reply.message = data.empty() ? "{\"error\":\"No Players Online\"}" : data.dump(); | ||||
| 				} else if (mg_match(http_msg->uri, mg_str((root_path + "teams").c_str()), NULL)) { | ||||
| 					// Get Teams | ||||
| 					const json data = Game::playerContainer.GetTeamContainer(); | ||||
|  | ||||
| 					reply.status = data.empty() ? 204 : 200; | ||||
| 					reply.message = data.empty() ? "{\"error\":\"No Teams Online\"}" : data.dump(); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		LOG_DEBUG("Replying with status %d: %s", reply.status, reply.message.c_str()); | ||||
| 		mg_http_reply(connection, reply.status, json_content_type, reply.message.c_str()); | ||||
| void HandleGET(HTTPReply& reply, const ChatWebAPI::eRoute& route , const std::string& body) { | ||||
| 	switch (route) { | ||||
| 		case ChatWebAPI::eRoute::PLAYERS: | ||||
| 			HandlePlayersRequest(reply); | ||||
| 			break; | ||||
| 		case ChatWebAPI::eRoute::TEAMS: | ||||
| 			HandleTeamsRequest(reply); | ||||
| 			break; | ||||
| 		case ChatWebAPI::eRoute::INVALID: | ||||
| 		default: | ||||
| 			HandleInvalidRoute(reply); | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void HandleAnnounceRequest(HTTPReply& reply, const std::optional<json>& data) { | ||||
| 	if (!CheckValidJSON(data, reply)) return; | ||||
|  | ||||
| 	const auto& good_data = data.value(); | ||||
| 	auto check = JSONUtils::CheckRequiredData(good_data, { "title", "message" }); | ||||
| 	if (!check.empty()) { | ||||
| 		reply.status = eHTTPStatusCode::BAD_REQUEST; | ||||
| 		reply.message = check; | ||||
| 	} else { | ||||
|  | ||||
| 		ChatPackets::Announcement announcement; | ||||
| 		announcement.title = good_data["title"]; | ||||
| 		announcement.message = good_data["message"]; | ||||
| 		announcement.Send(); | ||||
|  | ||||
| 		reply.status = eHTTPStatusCode::OK; | ||||
| 		reply.message = "{\"status\":\"Announcement Sent\"}"; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void HandlePOST(HTTPReply& reply, const ChatWebAPI::eRoute& route , const std::string& body) { | ||||
| 	auto data = GeneralUtils::TryParse<json>(body); | ||||
| 	switch (route) { | ||||
| 		case ChatWebAPI::eRoute::ANNOUNCE:{ | ||||
| 			HandleAnnounceRequest(reply, data.value()); | ||||
| 			break; | ||||
| 		} | ||||
| 		case ChatWebAPI::eRoute::INVALID: | ||||
| 		default: | ||||
| 			HandleInvalidRoute(reply); | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void HandleHTTPMessage(mg_connection* connection, const mg_http_message* http_msg) { | ||||
| 	HTTPReply reply; | ||||
| 	 | ||||
| 	if (!http_msg) { | ||||
| 		reply.status = eHTTPStatusCode::BAD_REQUEST; | ||||
| 		reply.message = "{\"error\":\"Invalid Request\"}"; | ||||
| 	} else { | ||||
| 		 | ||||
| 		// convert method from cstring to std string | ||||
| 		std::string method_string(http_msg->method.buf, http_msg->method.len); | ||||
| 		// get mehtod from mg to enum | ||||
| 		const eHTTPMethod method = magic_enum::enum_cast<eHTTPMethod>(method_string).value_or(eHTTPMethod::INVALID); | ||||
|  | ||||
| 		// convert uri from cstring to std string | ||||
| 		std::string uri(http_msg->uri.buf, http_msg->uri.len); | ||||
| 		// check for root path | ||||
| 		if (uri.find(root_path) == 0) { | ||||
| 			// remove root path from uri | ||||
| 			uri.erase(0, root_path.length()); | ||||
| 			// convert uri to uppercase | ||||
| 			std::transform(uri.begin(), uri.end(), uri.begin(), ::toupper); | ||||
| 			// convert uri string to route enum | ||||
| 			ChatWebAPI::eRoute route = magic_enum::enum_cast<ChatWebAPI::eRoute>(uri).value_or(ChatWebAPI::eRoute::INVALID); | ||||
|  | ||||
| 			// convert body from cstring to std string | ||||
| 			std::string body(http_msg->body.buf, http_msg->body.len); | ||||
|  | ||||
| 			switch (method) { | ||||
| 			case eHTTPMethod::GET: | ||||
| 				HandleGET(reply, route, body); | ||||
| 				break; | ||||
| 			case eHTTPMethod::POST: | ||||
| 				HandlePOST(reply, route, body); | ||||
| 				break; | ||||
| 			case eHTTPMethod::PUT:	 | ||||
| 			case eHTTPMethod::DELETE: | ||||
| 			case eHTTPMethod::HEAD:	 | ||||
| 			case eHTTPMethod::CONNECT: | ||||
| 			case eHTTPMethod::OPTIONS: | ||||
| 			case eHTTPMethod::TRACE: | ||||
| 			case eHTTPMethod::PATCH: | ||||
| 			case eHTTPMethod::INVALID: | ||||
| 			default: | ||||
| 				reply.status = eHTTPStatusCode::METHOD_NOT_ALLOWED; | ||||
| 				reply.message = "{\"error\":\"Invalid Method\"}"; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	mg_http_reply(connection, static_cast<int>(reply.status), json_content_type, reply.message.c_str()); | ||||
| } | ||||
|  | ||||
|  | ||||
| void HandleRequests(mg_connection* connection, int request, void* request_data) { | ||||
| 	switch (request) { | ||||
| 		case MG_EV_HTTP_MSG: | ||||
| 			HandleHTTPMessage(connection, static_cast<mg_http_message*>(request_data)); | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| ChatWebAPI::ChatWebAPI() { | ||||
| 	mg_log_set(MG_LL_NONE); | ||||
|   | ||||
| @@ -11,8 +11,19 @@ public: | ||||
| 	~ChatWebAPI(); | ||||
| 	void ReceiveRequests(); | ||||
| 	void Listen(); | ||||
| 	enum class eRoute { | ||||
| 		// GET | ||||
| 		PLAYERS, | ||||
| 		TEAMS, | ||||
| 		// POST | ||||
| 		ANNOUNCE, | ||||
| 		// INVALID | ||||
| 		INVALID | ||||
| 	}; | ||||
| private: | ||||
| 	mg_mgr mgr; | ||||
|  | ||||
|  | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										58
									
								
								dChatServer/JSONUtils.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								dChatServer/JSONUtils.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| #include "JSONUtils.h" | ||||
|  | ||||
| #include "json.hpp" | ||||
|  | ||||
| using json = nlohmann::json; | ||||
|  | ||||
| void to_json(json& data, const PlayerData& playerData) { | ||||
| 	data["id"] = playerData.playerID; | ||||
| 	data["name"] = playerData.playerName; | ||||
| 	data["gm_level"] = playerData.gmLevel; | ||||
| 	data["muted"] = playerData.GetIsMuted(); | ||||
|  | ||||
| 	auto& zoneID = data["zone_id"]; | ||||
| 	zoneID["map_id"] = playerData.zoneID.GetMapID(); | ||||
| 	zoneID["instance_id"] = playerData.zoneID.GetInstanceID(); | ||||
| 	zoneID["clone_id"] = playerData.zoneID.GetCloneID(); | ||||
| } | ||||
|  | ||||
| void to_json(json& data, const PlayerContainer& playerContainer) { | ||||
| 	data = playerContainer.GetAllPlayers(); | ||||
| } | ||||
|  | ||||
| void to_json(json& data, const TeamContainer& teamContainer) { | ||||
| 	for (auto& teamData : Game::playerContainer.GetTeams()) { | ||||
| 		if (!teamData) continue; | ||||
| 		data.push_back(*teamData); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void to_json(json& data, const TeamData& teamData) { | ||||
| 	data["id"] = teamData.teamID; | ||||
| 	data["loot_flag"] = teamData.lootFlag; | ||||
| 	data["local"] = teamData.local; | ||||
|  | ||||
| 	auto& leader = Game::playerContainer.GetPlayerData(teamData.leaderID); | ||||
| 	data["leader"] = leader.playerName; | ||||
|  | ||||
| 	auto& members = data["members"]; | ||||
| 	for (auto& member : teamData.memberIDs) { | ||||
| 		auto& playerData = Game::playerContainer.GetPlayerData(member); | ||||
|  | ||||
| 		if (!playerData) continue; | ||||
| 		members.push_back(playerData); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| std::string JSONUtils::CheckRequiredData(const json& data, const std::vector<std::string>& requiredData) { | ||||
| 	json check; | ||||
| 	check["error"] = json::array(); | ||||
| 	for (const auto& required : requiredData) { | ||||
| 		if (!data.contains(required)) { | ||||
| 			check["error"].push_back("Missing Parameter: " + required); | ||||
| 		} else if (data[required] == "") { | ||||
| 			check["error"].push_back("Empty Parameter: " + required); | ||||
| 		} | ||||
| 	} | ||||
| 	return check["error"].empty() ? "" : check.dump(); | ||||
| } | ||||
							
								
								
									
										17
									
								
								dChatServer/JSONUtils.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								dChatServer/JSONUtils.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| #ifndef __JSONUTILS_H__ | ||||
| #define __JSONUTILS_H__ | ||||
|  | ||||
| #include "json_fwd.hpp" | ||||
| #include "PlayerContainer.h" | ||||
|  | ||||
| void to_json(nlohmann::json& data, const PlayerData& playerData); | ||||
| void to_json(nlohmann::json& data, const PlayerContainer& playerContainer); | ||||
| void to_json(nlohmann::json& data, const TeamContainer& teamData); | ||||
| void to_json(nlohmann::json& data, const TeamData& teamData); | ||||
|  | ||||
| namespace JSONUtils { | ||||
| 	// check required data for reqeust | ||||
| 	std::string CheckRequiredData(const nlohmann::json& data, const std::vector<std::string>& requiredData); | ||||
| } | ||||
|  | ||||
| #endif // __JSONUTILS_H__ | ||||
| @@ -13,50 +13,6 @@ | ||||
| #include "dConfig.h" | ||||
| #include "MessageType/Chat.h" | ||||
|  | ||||
| #include "json.hpp" | ||||
|  | ||||
| using json = nlohmann::json; | ||||
|  | ||||
| void to_json(json& data, const PlayerData& playerData) { | ||||
| 	data["id"] = playerData.playerID; | ||||
| 	data["name"] = playerData.playerName; | ||||
| 	data["gm_level"] = playerData.gmLevel; | ||||
| 	data["muted"] = playerData.GetIsMuted(); | ||||
|  | ||||
| 	auto& zoneID = data["zone_id"]; | ||||
| 	zoneID["map_id"] = playerData.zoneID.GetMapID(); | ||||
| 	zoneID["instance_id"] = playerData.zoneID.GetInstanceID(); | ||||
| 	zoneID["clone_id"] = playerData.zoneID.GetCloneID(); | ||||
| } | ||||
|  | ||||
| void to_json(json& data, const PlayerContainer& playerContainer) { | ||||
| 	data = playerContainer.GetAllPlayers(); | ||||
| } | ||||
|  | ||||
| void to_json(json& data, const TeamContainer& teamContainer) { | ||||
| 	for (auto& teamData : Game::playerContainer.GetTeams()) { | ||||
| 		if (!teamData) continue; | ||||
| 		data.push_back(*teamData); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void to_json(json& data, const TeamData& teamData) { | ||||
| 	data["id"] = teamData.teamID; | ||||
| 	data["loot_flag"] = teamData.lootFlag; | ||||
| 	data["local"] = teamData.local; | ||||
|  | ||||
| 	auto& leader = Game::playerContainer.GetPlayerData(teamData.leaderID); | ||||
| 	data["leader"] = leader.playerName; | ||||
|  | ||||
| 	auto& members = data["members"]; | ||||
| 	for (auto& member : teamData.memberIDs) { | ||||
| 		auto& playerData = Game::playerContainer.GetPlayerData(member); | ||||
|  | ||||
| 		if (!playerData) continue; | ||||
| 		members.push_back(playerData); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void PlayerContainer::Initialize() { | ||||
| 	m_MaxNumberOfBestFriends = | ||||
| 		GeneralUtils::TryParse<uint32_t>(Game::config->GetValue("max_number_of_best_friends")).value_or(m_MaxNumberOfBestFriends); | ||||
|   | ||||
| @@ -6,7 +6,6 @@ | ||||
| #include "Game.h" | ||||
| #include "dServer.h" | ||||
| #include <unordered_map> | ||||
| #include "json_fwd.hpp" | ||||
|  | ||||
| enum class eGameMasterLevel : uint8_t; | ||||
|  | ||||
| @@ -55,10 +54,6 @@ struct PlayerData { | ||||
| 	bool isFTP = false; | ||||
| }; | ||||
|  | ||||
| void to_json(nlohmann::json& data, const PlayerData& playerData); | ||||
| void to_json(nlohmann::json& data, const PlayerContainer& playerContainer); | ||||
| void to_json(nlohmann::json& data, const TeamContainer& teamData); | ||||
| void to_json(nlohmann::json& data, const TeamData& teamData); | ||||
|  | ||||
| struct TeamData { | ||||
| 	TeamData(); | ||||
|   | ||||
							
								
								
									
										21
									
								
								dCommon/dEnums/eHTTPMethod.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								dCommon/dEnums/eHTTPMethod.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| #ifndef __EHTTPMETHODS__H__ | ||||
| #define __EHTTPMETHODS__H__ | ||||
|  | ||||
| #include <cstdint> | ||||
|  | ||||
| #include "magic_enum.hpp" | ||||
|  | ||||
| enum class eHTTPMethod : uint16_t { | ||||
| 	GET, | ||||
| 	POST, | ||||
| 	PUT, | ||||
| 	DELETE, | ||||
| 	HEAD, | ||||
| 	CONNECT, | ||||
| 	OPTIONS, | ||||
| 	TRACE, | ||||
| 	PATCH, | ||||
| 	INVALID | ||||
| }; | ||||
|  | ||||
| #endif // __EHTTPMETHODS__H__ | ||||
							
								
								
									
										72
									
								
								dCommon/dEnums/eHTTPStatusCode.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								dCommon/dEnums/eHTTPStatusCode.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| #ifndef __EHTTPSTATUSCODE__H__ | ||||
| #define __EHTTPSTATUSCODE__H__ | ||||
|  | ||||
| #include <cstdint> | ||||
| // verbose list of http codes | ||||
| // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status | ||||
| enum class eHTTPStatusCode : uint32_t { | ||||
| 	CONTINUE = 100, | ||||
| 	SWITCHING_PROTOCOLS = 101, | ||||
| 	PROCESSING = 102, | ||||
| 	EARLY_HINTS = 103, | ||||
| 	OK = 200, | ||||
| 	CREATED = 201, | ||||
| 	ACCEPTED = 202, | ||||
| 	NON_AUTHORITATIVE_INFORMATION = 203, | ||||
| 	NO_CONTENT = 204, | ||||
| 	RESET_CONTENT = 205, | ||||
| 	PARTIAL_CONTENT = 206, | ||||
| 	MULTI_STATUS = 207, | ||||
| 	ALREADY_REPORTED = 208, | ||||
| 	IM_USED = 226, | ||||
| 	MULTIPLE_CHOICES = 300, | ||||
| 	MOVED_PERMANENTLY = 301, | ||||
| 	FOUND = 302, | ||||
| 	SEE_OTHER = 303, | ||||
| 	NOT_MODIFIED = 304, | ||||
| 	USE_PROXY = 305, | ||||
| 	SWITCH_PROXY = 306, | ||||
| 	TEMPORARY_REDIRECT = 307, | ||||
| 	PERMANENT_REDIRECT = 308, | ||||
| 	BAD_REQUEST = 400, | ||||
| 	UNAUTHORIZED = 401, | ||||
| 	PAYMENT_REQUIRED = 402, | ||||
| 	FORBIDDEN = 403, | ||||
| 	NOT_FOUND = 404, | ||||
| 	METHOD_NOT_ALLOWED = 405, | ||||
| 	NOT_ACCEPTABLE = 406, | ||||
| 	PROXY_AUTHENTICATION_REQUIRED = 407, | ||||
| 	REQUEST_TIMEOUT = 408, | ||||
| 	CONFLICT = 409, | ||||
| 	GONE = 410, | ||||
| 	LENGTH_REQUIRED = 411, | ||||
| 	PRECONDITION_FAILED = 412, | ||||
| 	PAYLOAD_TOO_LARGE = 413, | ||||
| 	URI_TOO_LONG = 414, | ||||
| 	UNSUPPORTED_MEDIA_TYPE = 415, | ||||
| 	RANGE_NOT_SATISFIABLE = 416, | ||||
| 	EXPECTATION_FAILED = 417, | ||||
| 	I_AM_A_TEAPOT = 418, | ||||
| 	MISDIRECTED_REQUEST = 421, | ||||
| 	UNPROCESSABLE_ENTITY = 422, | ||||
| 	LOCKED = 423, | ||||
| 	FAILED_DEPENDENCY = 424, | ||||
| 	UPGRADE_REQUIRED = 426, | ||||
| 	PRECONDITION_REQUIRED = 428, | ||||
| 	TOO_MANY_REQUESTS = 429, | ||||
| 	REQUEST_HEADER_FIELDS_TOO_LARGE = 431, | ||||
| 	UNAVAILABLE_FOR_LEGAL_REASONS = 451, | ||||
| 	INTERNAL_SERVER_ERROR = 500, | ||||
| 	NOT_IMPLEMENTED = 501, | ||||
| 	BAD_GATEWAY = 502, | ||||
| 	SERVICE_UNAVAILABLE = 503, | ||||
| 	GATEWAY_TIMEOUT = 504, | ||||
| 	HTTP_VERSION_NOT_SUPPORTED = 505, | ||||
| 	VARIANT_ALSO_NEGOTIATES = 506, | ||||
| 	INSUFFICIENT_STORAGE = 507, | ||||
| 	LOOP_DETECTED = 508, | ||||
| 	NOT_EXTENDED = 510, | ||||
| 	NETWORK_AUTHENTICATION_REQUIRED = 511 | ||||
| }; | ||||
|  | ||||
| #endif // !__EHTTPSTATUSCODE__H__ | ||||
| @@ -97,3 +97,13 @@ void ChatPackets::SendMessageFail(const SystemAddress& sysAddr) { | ||||
| 	//docs say there's a wstring here-- no idea what it's for, or if it's even needed so leaving it as is for now. | ||||
| 	SEND_PACKET; | ||||
| } | ||||
|  | ||||
| void ChatPackets::Announcement::Send() { | ||||
| 	CBITSTREAM; | ||||
| 	BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, MessageType::Chat::GM_ANNOUNCE); | ||||
| 	bitStream.Write<uint32_t>(title.size()); | ||||
| 	bitStream.Write(title); | ||||
| 	bitStream.Write<uint32_t>(message.size()); | ||||
| 	bitStream.Write(message); | ||||
| 	SEND_PACKET_BROADCAST; | ||||
| } | ||||
|   | ||||
| @@ -27,6 +27,13 @@ struct FindPlayerRequest{ | ||||
| }; | ||||
|  | ||||
| namespace ChatPackets { | ||||
|  | ||||
| 	struct Announcement { | ||||
| 		std::string title; | ||||
| 		std::string message; | ||||
| 		void Send(); | ||||
| 	}; | ||||
|  | ||||
| 	void SendChatMessage(const SystemAddress& sysAddr, char chatChannel, const std::string& senderName, LWOOBJID playerObjectID, bool senderMythran, const std::u16string& message); | ||||
| 	void SendSystemMessage(const SystemAddress& sysAddr, const std::u16string& message, bool broadcast = false); | ||||
| 	void SendMessageFail(const SystemAddress& sysAddr); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Aaron Kimbre
					Aaron Kimbre