A macro is a good fit here because each branch does the same three things:

compare the string
assign the enum
print/log the same text

You can reduce it to this:
```c
#define HANDLE_BLOCK_SELECT(name, block_enum)                     \
    if (strcmp(block_name, name) == 0) {                          \
        target_player->selected_block = block_enum;               \
        printf("[console] Selected %s\n", name);                  \
        add_chat_message("[console] Selected " name);             \
    }

case CMD_SELECT:
    if (target_player && console_cmd.args[0] != '\0') {
        const char* block_name = console_cmd.args;

        HANDLE_BLOCK_SELECT("stone", BLOCK_STONE)
        else HANDLE_BLOCK_SELECT("dirt", BLOCK_DIRT)
        else HANDLE_BLOCK_SELECT("grass", BLOCK_GRASS)
        else HANDLE_BLOCK_SELECT("sand", BLOCK_SAND)
        else HANDLE_BLOCK_SELECT("wood", BLOCK_WOOD)
        else HANDLE_BLOCK_SELECT("glowstone", BLOCK_GLOWSTONE)
        else {
            printf("[console] Unknown block: %s\n", block_name);
        }
    }
    break;
```
A cleaner alternative in C is usually a lookup table instead of macros:
```c
typedef struct {
    const char* name;
    int block;
} BlockEntry;

static const BlockEntry block_table[] = {
    { "stone", BLOCK_STONE },
    { "dirt", BLOCK_DIRT },
    { "grass", BLOCK_GRASS },
    { "sand", BLOCK_SAND },
    { "wood", BLOCK_WOOD },
    { "glowstone", BLOCK_GLOWSTONE },
};

case CMD_SELECT:
    if (target_player && console_cmd.args[0] != '\0') {
        const char* block_name = console_cmd.args;
        int found = 0;

        for (size_t i = 0; i < sizeof(block_table)/sizeof(block_table[0]); i++) {
            if (strcmp(block_name, block_table[i].name) == 0) {
                target_player->selected_block = block_table[i].block;

                printf("[console] Selected %s\n", block_table[i].name);

                char msg[64];
                snprintf(msg, sizeof(msg),
                         "[console] Selected %s",
                         block_table[i].name);

                add_chat_message(msg);

                found = 1;
                break;
            }
        }

        if (!found) {
            printf("[console] Unknown block: %s\n", block_name);
        }
    }
    break;
```
The table approach scales much better if you add lots of block types later.