Compare commits

..

No commits in common. "a5e223859ca7d0b496b14124e646992ace46b2df" and "c93350a44c317cf7bfb31de30e6701a34d1e750a" have entirely different histories.

3 changed files with 14 additions and 109 deletions

View File

@ -7,140 +7,55 @@
#include <mods/feature/feature.h> #include <mods/feature/feature.h>
// Death Messages // Death Messages
static const char *monster_names[] = {"Zombie", "Creeper", "Skeleton", "Spider", "Zombie Pigman"}; static std::string get_death_message(Player *player) {
static std::string get_death_message(Player *player, Entity *cause, bool was_shot = false) { // Get Username
// Prepare Death Message std::string *username = &player->username;
std::string message = player->username;
// The cause // Prepare Death Message
if (cause) { std::string message;
// Entity cause message.append(username->c_str());
int type_id = cause->vtable->getEntityTypeId(cause); message.append(" has died");
int aux = cause->vtable->getAuxData(cause);
if (cause->vtable->isPlayer(cause)) {
// Another player
if (was_shot) {
message += " was shot by ";
} else {
message += " was killed by ";
}
message += ((Player *) cause)->username;
} else if (cause->vtable->getCreatureBaseType(cause) == 1) {
// Killed by a monster
if (was_shot) {
message += " was shot by a ";
} else {
message += " was killed by a ";
}
if (32 <= type_id && type_id <= 36) {
message += monster_names[type_id - 32];
} else {
// Unknown monster
message += "Mysterious Beast";
}
} else if (aux) {
// Throwable with owner
Level *level = player->level;
Entity *shooter = Level_getEntity(level, aux);
return get_death_message(player, shooter, true);
} else if (80 <= type_id || type_id <= 82) {
// Throwable without owner
message += " was shot under mysterious circumstances";
} else if (type_id == 65) {
// TNT
message += " was blown apart";
} else if (cause->vtable->isHangingEntity(cause)) {
// Painting?
message += " admired too much art";
} else {
if (was_shot) {
message += " was shot under mysterious circumstances";
} else {
message += " was killed under mysterious circumstances";
}
}
} else {
// Non-entity cause
if (was_shot) {
// Throwable with invalid owner
message += " was shot under mysterious circumstances";
} else {
// Anything else
message += " has died";
}
}
// Return // Return
return message; return message;
} }
static bool is_hurt = false;
static bool Mob_hurt_injection(Mob *mob, Entity *source, int dmg) {
// Call Original Method
is_hurt = true;
bool ret = Mob_hurt_non_virtual(mob, source, dmg);
is_hurt = false;
return ret;
}
// Death Message Logic // Death Message Logic
#define Player_death_injections(type) \ #define Player_actuallyHurt_injection(type) \
static void type##Player_die_injection(type##Player *player, Entity *cause) { \
/* Call Original Method */ \
type##Player_die_non_virtual(player, cause); \
\
/* Get Variable */ \
RakNetInstance *rak_net_instance = player->minecraft->rak_net_instance; \
/* Only Run On Server-Side */ \
if (rak_net_instance->vtable->isServer(rak_net_instance)) { \
/* Get Death Message */ \
std::string message = get_death_message((Player *) player, cause); \
\
/* Post Death Message */ \
ServerSideNetworkHandler *server_side_network_handler = (ServerSideNetworkHandler *) player->minecraft->network_handler; \
ServerSideNetworkHandler_displayGameMessage(server_side_network_handler, &message); \
} \
} \
\
static void type##Player_actuallyHurt_injection(type##Player *player, int32_t damage) { \ static void type##Player_actuallyHurt_injection(type##Player *player, int32_t damage) { \
/* Store Old Health */ \ /* Store Old Health */ \
int32_t old_health = player->health; \ int32_t old_health = player->health; \
\ \
/* Call Original Method */ \ /* Call Original Method */ \
type##Player_actuallyHurt_non_virtual(player, damage); \ type##Player_actuallyHurt_non_virtual(player, damage); \
if (is_hurt == true) return; \
\ \
/* Store New Health */ \ /* Store New Health */ \
int32_t new_health = player->health; \ int32_t new_health = player->health; \
\ \
/* Get Variables */ \ /* Get Variables */ \
RakNetInstance *rak_net_instance = player->minecraft->rak_net_instance; \ Minecraft *minecraft = player->minecraft; \
RakNetInstance *rak_net_instance = minecraft->rak_net_instance; \
/* Only Run On Server-Side */ \ /* Only Run On Server-Side */ \
if (rak_net_instance->vtable->isServer(rak_net_instance)) { \ if (rak_net_instance->vtable->isServer(rak_net_instance)) { \
/* Check Health */ \ /* Check Health */ \
if (new_health < 1 && old_health >= 1) { \ if (new_health < 1 && old_health >= 1) { \
/* Get Death Message */ \ /* Get Death Message */ \
std::string message = get_death_message((Player *) player, NULL); \ std::string message = get_death_message((Player *) player); \
\ \
/* Post Death Message */ \ /* Post Death Message */ \
ServerSideNetworkHandler *server_side_network_handler = (ServerSideNetworkHandler *) player->minecraft->network_handler; \ ServerSideNetworkHandler *server_side_network_handler = (ServerSideNetworkHandler *) minecraft->network_handler; \
ServerSideNetworkHandler_displayGameMessage(server_side_network_handler, &message); \ ServerSideNetworkHandler_displayGameMessage(server_side_network_handler, &message); \
} \ } \
} \ } \
} }
Player_actuallyHurt_injection(Local)
Player_death_injections(Local); Player_actuallyHurt_injection(Server)
Player_death_injections(Server);
// Init // Init
void init_death() { void init_death() {
// Death Messages // Death Messages
if (feature_has("Implement Death Messages", server_auto)) { if (feature_has("Implement Death Messages", server_auto)) {
patch_address(ServerPlayer_die_vtable_addr, (void *) ServerPlayer_die_injection);
patch_address(LocalPlayer_die_vtable_addr, (void *) LocalPlayer_die_injection);
patch_address(ServerPlayer_actuallyHurt_vtable_addr, (void *) ServerPlayer_actuallyHurt_injection); patch_address(ServerPlayer_actuallyHurt_vtable_addr, (void *) ServerPlayer_actuallyHurt_injection);
patch_address(LocalPlayer_actuallyHurt_vtable_addr, (void *) LocalPlayer_actuallyHurt_injection); patch_address(LocalPlayer_actuallyHurt_vtable_addr, (void *) LocalPlayer_actuallyHurt_injection);
patch_address(Mob_hurt_vtable_addr, (void *) Mob_hurt_injection);
overwrite_calls((void *) Mob_hurt_non_virtual, (void *) Mob_hurt_injection);
} }
} }

View File

@ -1,17 +1,8 @@
virtual-method void remove() = 0x10; virtual-method void remove() = 0x10;
virtual-method void tick() = 0x34; virtual-method void tick() = 0x34;
virtual-method bool interact(Player *with) = 0x6c; virtual-method bool interact(Player *with) = 0x6c;
virtual-method bool isPlayer() = 0x94;
virtual-method bool hurt(Entity *attacker, int damage) = 0xa4; virtual-method bool hurt(Entity *attacker, int damage) = 0xa4;
// See https://mcpirevival.miraheze.org/wiki/Minecraft:_Pi_Edition_Complete_Entity_List for these two
virtual-method int getEntityTypeId() = 0xdc; virtual-method int getEntityTypeId() = 0xdc;
virtual-method int getCreatureBaseType() = 0xe0;
virtual-method bool isMob() = 0xe8;
virtual-method bool isItemEntity() = 0xec;
// HangingEntity is a painting
virtual-method bool isHangingEntity() = 0xf0;
// The owner entity id for arrows/throwables, else 0
virtual-method int getAuxData() = 0xf4;
method void moveTo(float x, float y, float z, float yaw, float pitch) = 0x7a834; method void moveTo(float x, float y, float z, float yaw, float pitch) = 0x7a834;

View File

@ -1,2 +1 @@
extends TileEntity; extends TileEntity;