minecraft-pi-reborn/mods/src/chat/chat.cpp

142 lines
5.4 KiB
C++
Raw Normal View History

2021-02-16 17:26:40 +00:00
#include <string>
2021-02-22 03:16:05 +00:00
#include <cstring>
2021-02-16 17:26:40 +00:00
#include <cstdio>
#include <vector>
2022-04-28 03:38:30 +00:00
#ifndef MCPI_SERVER_MODE
2021-02-16 17:26:40 +00:00
#include <pthread.h>
2022-04-28 03:38:30 +00:00
#endif
2021-02-16 17:26:40 +00:00
#include <libreborn/libreborn.h>
2021-09-12 03:18:12 +00:00
#include <symbols/minecraft.h>
2022-04-28 03:38:30 +00:00
#ifndef MCPI_SERVER_MODE
#include <media-layer/core.h>
#endif
2021-02-16 17:26:40 +00:00
#include "../init/init.h"
2021-07-04 23:02:45 +00:00
#include "../feature/feature.h"
2021-09-12 03:18:12 +00:00
#ifndef MCPI_SERVER_MODE
2021-07-04 23:02:45 +00:00
#include "../input/input.h"
2022-03-14 23:09:25 +00:00
#endif
2021-02-16 17:26:40 +00:00
#include "chat.h"
2021-07-04 23:02:45 +00:00
// Store If Chat is Enabled
int _chat_enabled = 0;
2021-02-22 03:16:05 +00:00
// Message Limitations
2021-02-22 03:43:57 +00:00
#define MAX_CHAT_MESSAGE_LENGTH 512
2021-02-22 03:16:05 +00:00
2021-02-16 17:26:40 +00:00
// Send API Command
2021-09-12 03:18:12 +00:00
#ifndef MCPI_SERVER_MODE
2021-02-16 17:26:40 +00:00
static void send_api_command(unsigned char *minecraft, char *str) {
struct ConnectedClient client;
client.sock = -1;
client.str = "";
client.time = 0;
unsigned char *command_server = *(unsigned char **) (minecraft + Minecraft_command_server_property_offset);
if (command_server != NULL) {
(*CommandServer_parse)(command_server, client, str);
}
}
// Send API Chat Command
static void send_api_chat_command(unsigned char *minecraft, char *str) {
char *command = NULL;
2021-06-17 21:32:24 +00:00
safe_asprintf(&command, "chat.post(%s)\n", str);
2021-02-16 17:26:40 +00:00
send_api_command(minecraft, command);
free(command);
}
2022-03-14 23:09:25 +00:00
#endif
2021-02-16 17:26:40 +00:00
// Send Message To Players
static void send_message(unsigned char *server_side_network_handler, char *username, char *message) {
char *full_message = NULL;
2021-06-17 21:32:24 +00:00
safe_asprintf(&full_message, "<%s> %s", username, message);
2021-02-22 03:51:01 +00:00
sanitize_string(&full_message, MAX_CHAT_MESSAGE_LENGTH, 0);
2021-02-16 17:26:40 +00:00
(*ServerSideNetworkHandler_displayGameMessage)(server_side_network_handler, std::string(full_message));
free(full_message);
}
// Manually Send (And Loopback) ChatPacket
static void CommandServer_parse_CommandServer_dispatchPacket_injection(unsigned char *command_server, unsigned char *packet) {
unsigned char *minecraft = *(unsigned char **) (command_server + CommandServer_minecraft_property_offset);
if (minecraft != NULL) {
unsigned char *rak_net_instance = *(unsigned char **) (minecraft + Minecraft_rak_net_instance_property_offset);
unsigned char *rak_net_instance_vtable = *(unsigned char **) rak_net_instance;
RakNetInstance_isServer_t RakNetInstance_isServer = *(RakNetInstance_isServer_t *) (rak_net_instance_vtable + RakNetInstance_isServer_vtable_offset);
if ((*RakNetInstance_isServer)(rak_net_instance)) {
// Hosting Multiplayer
char *message = *(char **) (packet + ChatPacket_message_property_offset);
2021-02-17 16:31:01 +00:00
unsigned char *server_side_network_handler = *(unsigned char **) (minecraft + Minecraft_network_handler_property_offset);
2021-02-16 17:26:40 +00:00
send_message(server_side_network_handler, *default_username, message);
} else {
// Client
RakNetInstance_send_t RakNetInstance_send = *(RakNetInstance_send_t *) (rak_net_instance_vtable + RakNetInstance_send_vtable_offset);
(*RakNetInstance_send)(rak_net_instance, packet);
}
}
}
// Handle ChatPacket Server-Side
2021-09-28 18:04:05 +00:00
static void ServerSideNetworkHandler_handle_ChatPacket_injection(unsigned char *server_side_network_handler, RakNet_RakNetGUID *rak_net_guid, unsigned char *chat_packet) {
2021-02-16 17:26:40 +00:00
unsigned char *player = (*ServerSideNetworkHandler_getPlayer)(server_side_network_handler, rak_net_guid);
if (player != NULL) {
char *username = *(char **) (player + Player_username_property_offset);
char *message = *(char **) (chat_packet + ChatPacket_message_property_offset);
send_message(server_side_network_handler, username, message);
}
}
2021-09-12 03:18:12 +00:00
#ifndef MCPI_SERVER_MODE
2021-02-16 17:26:40 +00:00
// Message Queue
static pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER;
static std::vector<std::string> queue;
// Add To Queue
2021-06-17 21:32:24 +00:00
void _chat_queue_message(char *message) {
2021-02-16 17:26:40 +00:00
// Lock
pthread_mutex_lock(&queue_mutex);
// Add
std::string str;
str.append(message);
queue.push_back(str);
// Unlock
pthread_mutex_unlock(&queue_mutex);
}
// Empty Queue
2021-02-16 22:08:43 +00:00
unsigned int old_chat_counter = 0;
2021-07-04 23:02:45 +00:00
static void send_queued_messages(unsigned char *minecraft) {
2021-02-16 17:26:40 +00:00
// Lock
pthread_mutex_lock(&queue_mutex);
2021-02-16 22:08:43 +00:00
// If Message Was Submitted, No Other Chat Windows Are Open, And The Game Is Not Paused, Then Re-Lock Cursor
unsigned int new_chat_counter = chat_get_counter();
if (old_chat_counter > new_chat_counter && new_chat_counter == 0 && (*(unsigned char **) (minecraft + Minecraft_screen_property_offset)) == NULL) {
2022-04-28 03:38:30 +00:00
// Unlock UI
media_set_interactable(1);
2021-02-16 22:08:43 +00:00
}
old_chat_counter = new_chat_counter;
2021-02-16 17:26:40 +00:00
// Loop
for (unsigned int i = 0; i < queue.size(); i++) {
send_api_chat_command(minecraft, (char *) queue[i].c_str());
}
queue.clear();
// Unlock
pthread_mutex_unlock(&queue_mutex);
}
2022-03-14 23:09:25 +00:00
#endif
2021-02-16 17:26:40 +00:00
// Init
void init_chat() {
2022-04-10 00:01:16 +00:00
_chat_enabled = feature_has("Implement Chat", server_enabled);
2021-07-04 23:02:45 +00:00
if (_chat_enabled) {
// Disable Original ChatPacket Loopback
unsigned char disable_chat_packet_loopback_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
patch((void *) 0x6b490, disable_chat_packet_loopback_patch);
// Manually Send (And Loopback) ChatPacket
overwrite_call((void *) 0x6b518, (void *) CommandServer_parse_CommandServer_dispatchPacket_injection);
// Re-Broadcast ChatPacket
patch_address(ServerSideNetworkHandler_handle_ChatPacket_vtable_addr, (void *) ServerSideNetworkHandler_handle_ChatPacket_injection);
// Send Messages On Input Tick
2021-09-12 03:18:12 +00:00
#ifndef MCPI_SERVER_MODE
2021-07-04 23:02:45 +00:00
input_run_on_tick(send_queued_messages);
2022-03-14 23:09:25 +00:00
#endif
2021-07-04 23:02:45 +00:00
}
}