Better Examples

This commit is contained in:
TheBrokenRail 2022-06-26 21:17:52 -04:00
parent a94708a1ae
commit bfa0567ac9
13 changed files with 109 additions and 21 deletions

2
.gitignore vendored
View File

@ -1,7 +1,7 @@
out out
debian/tmp debian/tmp
.vscode .vscode
build build*
CMakeLists.txt.user CMakeLists.txt.user
*.autosave *.autosave
AppImageBuilder.yml AppImageBuilder.yml

View File

@ -1 +0,0 @@
build

View File

@ -1,7 +1,8 @@
# Example Mod # Example Mods
This is an example of a mod that cane be built using the modding SDK. This is an example of a mod that cane be built using the modding SDK.
This specific mod adds even more items and blocks to the Creative Inventory. It was originally by [@Bigjango13](https://github.com/bigjango13). * **Expanded Creative Mod**: This specific mod adds even more items and blocks to the Creative Inventory. It was originally by [@Bigjango13](https://github.com/bigjango13).
* **Chat Commands Mod**: This specific mod makes an chat message starting with a ``/`` handled by the MCPI API.
## The SDK ## The SDK
The modding SDK is a collection of exported CMake targets that allows anyone to create their own MCPI mod! The modding SDK is a collection of exported CMake targets that allows anyone to create their own MCPI mod!

14
example-mods/chat-commands/.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
out
debian/tmp
.vscode
build*
CMakeLists.txt.user
*.autosave
AppImageBuilder.yml
appimage-builder-cache
appimage-build
AppDir
*.zsync
*.AppImage
core*
qemu_*

View File

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.16.0)
# Build For ARM
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
# Start Project
project(chat-commands)
# Include SDK
include("$ENV{HOME}/.minecraft-pi/sdk/lib/minecraft-pi-reborn-client/sdk/sdk.cmake")
# Build
add_library(chat-commands SHARED chat-commands.cpp)
target_link_libraries(chat-commands mods-headers reborn-patch symbols chat misc)

View File

@ -0,0 +1,25 @@
// Headers
#include <libreborn/libreborn.h>
#include <symbols/minecraft.h>
#include <mods/chat/chat.h>
#include <mods/misc/misc.h>
// The Actual Mod
HOOK(chat_handle_packet_send, void, (unsigned char *minecraft, unsigned char *packet)) {
// Get Message
char *message = *(char **) (packet + ChatPacket_message_property_offset);
if (message[0] == '/') {
// API Command
unsigned char *gui = minecraft + Minecraft_gui_property_offset;
std::string out = chat_send_api_command(minecraft, &message[1]);
if (out.length() > 0 && out[out.length() - 1] == '\n') {
out[out.length() - 1] = '\0';
}
misc_add_message(gui, out.c_str());
} else {
// Call Original Method
ensure_chat_handle_packet_send();
(*real_chat_handle_packet_send)(minecraft, packet);
}
}

View File

@ -0,0 +1,14 @@
out
debian/tmp
.vscode
build*
CMakeLists.txt.user
*.autosave
AppImageBuilder.yml
appimage-builder-cache
appimage-build
AppDir
*.zsync
*.AppImage
core*
qemu_*

View File

@ -2,6 +2,12 @@
#include <libreborn/libreborn.h> #include <libreborn/libreborn.h>
#ifdef __cplusplus
#include <string>
// Send API Command
std::string chat_send_api_command(unsigned char *minecraft, char *str);
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -13,6 +19,7 @@ unsigned int chat_get_counter();
// Override using the HOOK() macro to provide customized chat behavior. // Override using the HOOK() macro to provide customized chat behavior.
void chat_send_message(unsigned char *server_side_network_handler, char *username, char *message); void chat_send_message(unsigned char *server_side_network_handler, char *username, char *message);
void chat_handle_packet_send(unsigned char *minecraft, unsigned char *packet);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -10,6 +10,9 @@ void misc_run_on_tick(misc_update_function_t function);
void Level_saveLevelData_injection(unsigned char *level); void Level_saveLevelData_injection(unsigned char *level);
// Use this instead of directly calling Gui::addMessage(), it has proper logging!
void misc_add_message(unsigned char *gui, const char *text);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -29,22 +29,25 @@ int _chat_enabled = 0;
#define MAX_CHAT_MESSAGE_LENGTH 512 #define MAX_CHAT_MESSAGE_LENGTH 512
// Send API Command // Send API Command
#ifndef MCPI_SERVER_MODE std::string chat_send_api_command(unsigned char *minecraft, char *str) {
static void send_api_command(unsigned char *minecraft, char *str) {
struct ConnectedClient client; struct ConnectedClient client;
client.sock = -1; client.sock = -1;
client.str = ""; client.str = "";
client.time = 0; client.time = 0;
unsigned char *command_server = *(unsigned char **) (minecraft + Minecraft_command_server_property_offset); unsigned char *command_server = *(unsigned char **) (minecraft + Minecraft_command_server_property_offset);
if (command_server != NULL) { if (command_server != NULL) {
(*CommandServer_parse)(command_server, client, str); return (*CommandServer_parse)(command_server, client, str);
} else {
return "";
} }
} }
#ifndef MCPI_SERVER_MODE
// Send API Chat Command // Send API Chat Command
static void send_api_chat_command(unsigned char *minecraft, char *str) { static void send_api_chat_command(unsigned char *minecraft, char *str) {
char *command = NULL; char *command = NULL;
safe_asprintf(&command, "chat.post(%s)\n", str); safe_asprintf(&command, "chat.post(%s)\n", str);
send_api_command(minecraft, command); chat_send_api_command(minecraft, command);
free(command); free(command);
} }
#endif #endif
@ -57,24 +60,28 @@ void chat_send_message(unsigned char *server_side_network_handler, char *usernam
(*ServerSideNetworkHandler_displayGameMessage)(server_side_network_handler, std::string(full_message)); (*ServerSideNetworkHandler_displayGameMessage)(server_side_network_handler, std::string(full_message));
free(full_message); free(full_message);
} }
// Handle Chat packet Send
void chat_handle_packet_send(unsigned char *minecraft, unsigned char *packet) {
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);
unsigned char *server_side_network_handler = *(unsigned char **) (minecraft + Minecraft_network_handler_property_offset);
chat_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);
}
}
// Manually Send (And Loopback) ChatPacket // Manually Send (And Loopback) ChatPacket
static void CommandServer_parse_CommandServer_dispatchPacket_injection(unsigned char *command_server, unsigned char *packet) { 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); unsigned char *minecraft = *(unsigned char **) (command_server + CommandServer_minecraft_property_offset);
if (minecraft != NULL) { if (minecraft != NULL) {
unsigned char *rak_net_instance = *(unsigned char **) (minecraft + Minecraft_rak_net_instance_property_offset); chat_handle_packet_send(minecraft, packet);
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);
unsigned char *server_side_network_handler = *(unsigned char **) (minecraft + Minecraft_network_handler_property_offset);
chat_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);
}
} }
} }

View File

@ -35,6 +35,9 @@ static void Gui_addMessage_injection(unsigned char *gui, std::string const& text
// Free // Free
free(new_message); free(new_message);
} }
void misc_add_message(unsigned char *gui, const char *text) {
Gui_addMessage_injection(gui, text);
}
// Print Progress Reports // Print Progress Reports
static int last_progress = -1; static int last_progress = -1;