Make polling chat work in MP

This commit is contained in:
Bigjango13 2024-10-30 00:06:04 -07:00
parent c93f6f87bc
commit 5c264736de
9 changed files with 74 additions and 40 deletions

View File

@ -10,8 +10,10 @@ extern "C" {
std::string chat_send_api_command(const Minecraft *minecraft, const std::string &str);
// Override using the HOOK() macro to provide customized chat behavior.
void chat_send_message(ServerSideNetworkHandler *server_side_network_handler, const char *username, const char *message);
void chat_send_message(ServerSideNetworkHandler *server_side_network_handler, Entity *sender, const char *message);
void chat_handle_packet_send(const Minecraft *minecraft, ChatPacket *packet);
void chat_set_already_added(bool already_added);
bool chat_already_added();
bool chat_is_sending();
}

View File

@ -27,11 +27,13 @@ void misc_run_on_game_key_press(const std::function<bool(Minecraft *, int)> &fun
void misc_run_on_key_press(const std::function<bool(Minecraft *, int)> &func);
void misc_run_on_creative_inventory_setup(const std::function<void(FillingContainer *)> &function);
void misc_run_on_swap_buffers(const std::function<void()> &function);
std::string misc_get_player_username(Player *player, bool convert_to_utf = false);
std::string misc_get_player_username(Player *player);
std::map<int, std::string> &misc_get_entity_names();
std::string misc_get_entity_name(Entity *entity);
std::string misc_get_entity_name_upper(Entity *entity);
std::string misc_get_entity_type_name(Entity *entity);
std::string misc_get_entity_name(Entity *entity, bool convert_to_utf = false);
std::string misc_get_entity_name_upper(Entity *entity, bool convert_to_utf = false);
Entity *misc_make_entity_from_id(Level *level, int id);
void api_add_chat_event(Entity *sender, const std::string &message);
std::string misc_base64_encode(const std::string &data);
std::string misc_base64_decode(const std::string &input);

View File

@ -72,7 +72,7 @@ static std::string getEntityData(CommandServer *commandserver, Entity *entity) {
// type
std::to_string(entity->getEntityTypeId()) + "," +
// name
empty_fallback(misc_get_entity_name_upper(entity), entity->id) + "," +
empty_fallback(misc_get_entity_name_upper(entity, true), entity->id) + "," +
// x
std::to_string(x) + "," +
// y
@ -278,7 +278,7 @@ std::string CommandServer_parse_injection(CommandServer_parse_t old, CommandServ
if (entity == NULL) {
WARN("Player (or Entity) [%i] not found in entity.getName.", id);
}
return empty_fallback(misc_get_entity_name_upper(entity), entity->id) + "\n";
return empty_fallback(misc_get_entity_name_upper(entity, true), entity->id) + "\n";
} else if (cmd == "world.getEntities") {
int type;
int ret = sscanf(args.c_str(), "%d", &type);
@ -661,21 +661,31 @@ static void Throwable_tick_Throwable_onHit_injection(Throwable *self, HitResult
static void Gui_addMessage_injection(Gui_addMessage_t original, Gui *gui, const std::string &text) {
static bool recursing = false;
if (recursing) {
if (recursing || chat_already_added()) {
chat_set_already_added(false);
original(gui, text);
} else {
chatEvents.push(ChatEvent{
text.substr(gui->minecraft->player->username.size() + 3),
chat_is_sending() ? gui->minecraft->player->id : 0
});
if (chat_is_sending()) {
std::string message = text.substr(gui->minecraft->player->username.size() + 3);
api_add_chat_event((Entity *) gui->minecraft->player, text);
} else {
api_add_chat_event(NULL, text);
}
recursing = true;
original(gui, text);
recursing = false;
}
}
bool enabled = false;
void api_add_chat_event(Entity *sender, const std::string &message) {
if (!enabled) return;
chatEvents.push(ChatEvent{message, sender ? sender->id : 0});
}
void init_api() {
if (feature_has("Implement RaspberryJuice API", server_enabled)) {
enabled = true;
overwrite_calls(CommandServer_parse, CommandServer_parse_injection);
overwrite_calls(Arrow_tick, Arrow_tick_injection);
overwrite_call((void *) 0x8b1e8, (void *) Arrow_tick_HitResult_constructor_injection);

View File

@ -5,6 +5,7 @@
#include <libreborn/libreborn.h>
#include <symbols/minecraft.h>
#include <mods/misc/misc.h>
#include <mods/init/init.h>
#include <mods/feature/feature.h>
#include "chat-internal.h"
@ -34,7 +35,22 @@ static void send_api_chat_command(const Minecraft *minecraft, const char *str) {
std::string _chat_get_prefix(const char *username) {
return std::string("<") + username + "> ";
}
void chat_send_message(ServerSideNetworkHandler *server_side_network_handler, const char *username, const char *message) {
static bool _chat_already_added = false;
bool chat_already_added() {
return _chat_already_added;
}
void chat_set_already_added(bool already_added) {
_chat_already_added = already_added;
}
void chat_send_message(ServerSideNetworkHandler *server_side_network_handler, Entity *sender, const char *message) {
const char *username = NULL;
if (sender && sender->isPlayer()) {
_chat_already_added = true;
api_add_chat_event(sender, message);
username = ((Player *) sender)->username.c_str();
} else {
username = Strings::default_username;
}
std::string full_message = _chat_get_prefix(username) + message;
char *raw_str = strdup(full_message.c_str());
ALLOC_CHECK(raw_str);
@ -50,7 +66,7 @@ void chat_handle_packet_send(const Minecraft *minecraft, ChatPacket *packet) {
// Hosting Multiplayer
const char *message = packet->message.c_str();
ServerSideNetworkHandler *server_side_network_handler = (ServerSideNetworkHandler *) minecraft->network_handler;
chat_send_message(server_side_network_handler, Strings::default_username, (char *) message);
chat_send_message(server_side_network_handler, NULL, (char *) message);
} else {
// Client
rak_net_instance->send(*(Packet *) packet);
@ -69,9 +85,8 @@ static void CommandServer_parse_CommandServer_dispatchPacket_injection(const Com
static void ServerSideNetworkHandler_handle_ChatPacket_injection(ServerSideNetworkHandler *server_side_network_handler, const RakNet_RakNetGUID &rak_net_guid, ChatPacket *chat_packet) {
const Player *player = server_side_network_handler->getPlayer(rak_net_guid);
if (player != nullptr) {
const char *username = player->username.c_str();
const char *message = chat_packet->message.c_str();
chat_send_message(server_side_network_handler, username, message);
chat_send_message(server_side_network_handler, (Entity *) player, message);
}
}

View File

@ -128,13 +128,8 @@ static std::vector<std::string> get_debug_info_right(const Minecraft *minecraft)
z = entity->z;
type = "Entity";
type_info.push_back("ID: " + std::to_string(entity->id));
std::string type_str = "Type: ";
if (entity->isPlayer()) {
type_str += "Player";
} else {
type_str += misc_get_entity_names()[entity->getEntityTypeId()];
}
type_str += " (" + std::to_string(entity->getEntityTypeId()) + ")";
std::string type_str = "Type: " + misc_get_entity_type_name(entity)
+ " (" + std::to_string(entity->getEntityTypeId()) + ")";
type_info.push_back(type_str);
if (entity->isMob()) {
Mob *mob = (Mob *) entity;

View File

@ -135,8 +135,7 @@ void misc_render_background(int color, const Minecraft *minecraft, const int x,
}
// Get Player's Username
std::string misc_get_player_username(Player *player, bool convert_to_utf) {
if (!convert_to_utf) return player->username;
std::string misc_get_player_username(Player *player) {
const std::string *username = &player->username;
char *safe_username_c = from_cp437(username->c_str());
std::string safe_username = safe_username_c;
@ -146,8 +145,6 @@ std::string misc_get_player_username(Player *player, bool convert_to_utf) {
std::map<int, std::string> &misc_get_entity_names() {
static std::map<int, std::string> entity_names = {
// Unsavables
{0, "Unknown"},
// Animals
{10, "Chicken"}, {11, "Cow"}, {12, "Pig"}, {13, "Sheep"},
// Hostiles
@ -161,27 +158,36 @@ std::map<int, std::string> &misc_get_entity_names() {
};
std::string misc_get_entity_name(Entity *entity) {
if (entity == NULL) {
return "";
} else if (entity->isPlayer()) {
return misc_get_player_username((Player *) entity);
} else {
int type = entity->getEntityTypeId();
std::map<int, std::string> &names = misc_get_entity_names();
if (names.find(type) != names.end()) return names[type];
return "";
}
std::string misc_get_entity_name(Entity *entity, bool convert_to_utf) {
if (!entity) return "";
if (entity->isPlayer()) return convert_to_utf ? misc_get_player_username((Player *) entity) : ((Player *) entity)->username;
return misc_get_entity_type_name(entity);
}
std::string misc_get_entity_name_upper(Entity *entity) {
std::string ret = misc_get_entity_name(entity);
std::string misc_get_entity_name_upper(Entity *entity, bool convert_to_utf) {
std::string ret = misc_get_entity_name(entity, convert_to_utf);
if (entity != NULL && !entity->isPlayer()) {
for (char &c : ret) c = toupper(c);
}
return ret;
}
std::string misc_get_entity_type_name(Entity *entity) {
if (!entity) {
return "";
} else if (entity->isPlayer()) {
return "Player";
} else {
int type = entity->getEntityTypeId();
if (type == 0 && entity->vtable == (Entity_vtable *) Particle_vtable_base) return "Particle";
if (type == 0 && entity->vtable == (Entity_vtable *) TripodCamera_vtable_base) return "TripodCamera";
if (type == 0 && entity->vtable == (Entity_vtable *) CameraEntity_vtable_base) return "CameraEntity";
std::map<int, std::string> &names = misc_get_entity_names();
if (names.find(type) != names.end()) return names[type];
return "";
}
}
Entity *misc_make_entity_from_id(Level *level, int id) {
if (id < 0x40) {
return (Entity *) MobFactory::CreateMob(id, level);

View File

@ -129,7 +129,7 @@ static void find_players(Minecraft *minecraft, const std::string &target_usernam
for (std::size_t i = 0; i < players.size(); i++) {
// Iterate Players
Player *player = players[i];
std::string username = misc_get_player_username(player, true);
std::string username = misc_get_player_username(player);
if (all_players || username == target_username) {
// Run Callback
callback(minecraft, username, player);

View File

@ -70,6 +70,7 @@ set(SRC
src/entity/Arrow.def
src/entity/ArrowRenderer.def
src/entity/PaintingRenderer.def
src/entity/Particle.def
src/entity/Throwable.def
src/level/container/FillingContainer.def
src/level/container/Container.def

View File

@ -0,0 +1,3 @@
extends Entity;
vtable 0x105b68;