Make Biome-Tinted Grass Not Suck
This commit is contained in:
parent
aea31dd4c8
commit
5d8aa28113
@ -8,3 +8,4 @@
|
||||
| [RetDec](https://retdec.com) | Used For Decompiling Minecraft: Pi Edition |
|
||||
| [minecraft-linux/mcpelauncher-core](https://github.com/minecraft-linux/mcpelauncher-core/blob/6b5e17b5685a612143297ae4595bdd12327284f3/src/patch_utils.cpp#L42) | Original Function Overwrite Code |
|
||||
| [Hooking C Functions at Runtime - Thomas Finch](http://thomasfinch.me/blog/2015/07/24/Hooking-C-Functions-At-Runtime.html) | Original Patching Code |
|
||||
| [ReMinecraftPE](https://github.com/ReMinecraftPE/mcpe) | A Lot Of Decompiled Code |
|
@ -19,7 +19,7 @@ install(
|
||||
DESTINATION "${MCPI_INSTALL_DIR}/data/images/item"
|
||||
)
|
||||
install(
|
||||
FILES "mojang/shadow.png" "mojang/vignette.png"
|
||||
FILES "mojang/shadow.png" "mojang/vignette.png" "mojang/grasscolor.png"
|
||||
DESTINATION "${MCPI_INSTALL_DIR}/data/images/misc"
|
||||
)
|
||||
|
||||
|
BIN
images/mojang/grasscolor.png
Normal file
BIN
images/mojang/grasscolor.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
@ -1,42 +1,54 @@
|
||||
#include <libreborn/patch.h>
|
||||
#include <cstdint>
|
||||
|
||||
#include <libreborn/patch.h>
|
||||
#include <symbols/minecraft.h>
|
||||
|
||||
#include <mods/feature/feature.h>
|
||||
#include <mods/extend/extend.h>
|
||||
|
||||
#include "misc-internal.h"
|
||||
|
||||
// Change Grass Color
|
||||
static int32_t get_color(LevelSource *level_source, int32_t x, int32_t z) {
|
||||
// Get Biome
|
||||
const Biome *biome = level_source->getBiome(x, z);
|
||||
if (biome == nullptr) {
|
||||
return 0;
|
||||
static bool grass_colors_loaded = false;
|
||||
#define GRASS_COLORS_SIZE 256
|
||||
static uint32_t grass_colors[GRASS_COLORS_SIZE][GRASS_COLORS_SIZE];
|
||||
static void Minecraft_init_injection(Minecraft_init_t original, Minecraft *self) {
|
||||
// Call Original Method
|
||||
original(self);
|
||||
// Load
|
||||
const uint32_t id = self->textures->loadTexture("misc/grasscolor.png", true);
|
||||
const Texture *data = self->textures->getTemporaryTextureData(id);
|
||||
if (data == nullptr || data->width != GRASS_COLORS_SIZE || data->height != GRASS_COLORS_SIZE) {
|
||||
return;
|
||||
}
|
||||
// Return
|
||||
return biome->color;
|
||||
}
|
||||
#define BIOME_BLEND_SIZE 7
|
||||
static int32_t GrassTile_getColor_injection(__attribute__((unused)) GrassTile_getColor_t original, __attribute__((unused)) GrassTile *tile, LevelSource *level_source, const int32_t x, __attribute__((unused)) int32_t y, const int32_t z) {
|
||||
int r_sum = 0;
|
||||
int g_sum = 0;
|
||||
int b_sum = 0;
|
||||
int color_sum = 0;
|
||||
const int x_start = x - (BIOME_BLEND_SIZE / 2);
|
||||
const int z_start = z - (BIOME_BLEND_SIZE / 2);
|
||||
for (int x_offset = 0; x_offset < BIOME_BLEND_SIZE; x_offset++) {
|
||||
for (int z_offset = 0; z_offset < BIOME_BLEND_SIZE; z_offset++) {
|
||||
const int32_t color = get_color(level_source, x_start + x_offset, z_start + z_offset);
|
||||
r_sum += (color >> 16) & 0xff;
|
||||
g_sum += (color >> 8) & 0xff;
|
||||
b_sum += color & 0xff;
|
||||
color_sum++;
|
||||
const uint32_t *texture = (uint32_t *) data->data;
|
||||
// Copy
|
||||
for (int y = 0; y < GRASS_COLORS_SIZE; y++) {
|
||||
for (int x = 0; x < GRASS_COLORS_SIZE; x++) {
|
||||
grass_colors[y][x] = texture[(y * GRASS_COLORS_SIZE) + x];
|
||||
}
|
||||
}
|
||||
const int r_avg = r_sum / color_sum;
|
||||
const int g_avg = g_sum / color_sum;
|
||||
const int b_avg = b_sum / color_sum;
|
||||
return (r_avg << 16) | (g_avg << 8) | b_avg;
|
||||
grass_colors_loaded = true;
|
||||
}
|
||||
static int32_t GrassTile_getColor_injection(__attribute__((unused)) GrassTile_getColor_t original, __attribute__((unused)) GrassTile *tile, LevelSource *level_source, const int32_t x, __attribute__((unused)) int32_t y, const int32_t z) {
|
||||
// Get Level
|
||||
Level *level = ((Region *) level_source)->level;
|
||||
// Find Biome Temperature
|
||||
BiomeSource *biome_source = level->getBiomeSource();
|
||||
biome_source->getBiomeBlock(x, z, 1, 1);
|
||||
const float temperature = biome_source->temperature[0];
|
||||
float downfall = biome_source->downfall[0];
|
||||
// Get Grass Color
|
||||
downfall *= temperature;
|
||||
const int xx = (int) ((1 - temperature) * (GRASS_COLORS_SIZE - 1));
|
||||
const int yy = (int) ((1 - downfall) * (GRASS_COLORS_SIZE - 1));
|
||||
uint32_t color = grass_colors[yy][xx];
|
||||
// Convert From ABGR To ARGB
|
||||
const uint8_t b = (color >> 16) & 0xff;
|
||||
const uint8_t g = (color >> 8) & 0xff;
|
||||
const uint8_t r = color & 0xff;
|
||||
color = (r << 16) | (g << 8) | b;
|
||||
return (int32_t) color;
|
||||
}
|
||||
static int32_t TallGrass_getColor_injection(TallGrass_getColor_t original, TallGrass *tile, LevelSource *level_source, const int32_t x, const int32_t y, const int32_t z) {
|
||||
const int32_t original_color = original(tile, level_source, x, y, z);
|
||||
@ -47,6 +59,32 @@ static int32_t TallGrass_getColor_injection(TallGrass_getColor_t original, TallG
|
||||
}
|
||||
}
|
||||
|
||||
// Grass Side Tinting
|
||||
CUSTOM_VTABLE(grass_side, Tile) {
|
||||
vtable->shouldRenderFace = [](Tile *self, LevelSource *level_source, const int x, const int y, const int z, const int face) {
|
||||
return face != 0 && face != 1 && Tile_vtable::base->shouldRenderFace(self, level_source, x, y, z, face);
|
||||
};
|
||||
vtable->getColor = [](Tile *self, LevelSource *level_source, const int32_t x, const int32_t y, const int32_t z) {
|
||||
return GrassTile_getColor_injection(nullptr, (GrassTile *) self, level_source, x, y, z);
|
||||
};
|
||||
}
|
||||
static Tile *get_fake_grass_side_tile() {
|
||||
static Tile *out = nullptr;
|
||||
if (out == nullptr) {
|
||||
out = Tile::allocate();
|
||||
out->constructor(0, 38, Material::dirt);
|
||||
out->vtable = get_grass_side_vtable();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
static bool TileRenderer_tesselateBlockInWorld_injection(TileRenderer_tesselateBlockInWorld_t original, TileRenderer *self, Tile *tile, const int x, const int y, const int z) {
|
||||
const bool ret = original(self, tile, x, y, z);
|
||||
if (tile == Tile::grass && tile->getTexture3((LevelSource *) self->level, x, y, z, 2) == 3) {
|
||||
original(self, get_fake_grass_side_tile(), x, y, z);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// No Block Tinting
|
||||
template <typename T>
|
||||
static int32_t Tile_getColor_injection(__attribute__((unused)) const std::function<int(T *, LevelSource *, int, int, int)> &original, __attribute__((unused)) T *self, __attribute__((unused)) LevelSource *level_source, __attribute__((unused)) int x, __attribute__((unused)) int y, __attribute__((unused)) int z) {
|
||||
@ -57,8 +95,14 @@ static int32_t Tile_getColor_injection(__attribute__((unused)) const std::functi
|
||||
void _init_misc_tinting() {
|
||||
// Change Grass Color
|
||||
if (feature_has("Add Biome Colors To Grass", server_disabled)) {
|
||||
overwrite_calls(Minecraft_init, Minecraft_init_injection);
|
||||
overwrite_calls(GrassTile_getColor, GrassTile_getColor_injection);
|
||||
overwrite_calls(TallGrass_getColor, TallGrass_getColor_injection);
|
||||
// Fancy Grass Side
|
||||
// This Requires Alpha Testing On The Opaque Render-Layer, Which Could Hurt Performance
|
||||
overwrite_calls(TileRenderer_tesselateBlockInWorld, TileRenderer_tesselateBlockInWorld_injection);
|
||||
unsigned char nop_patch[4] = {0x00, 0xf0, 0x20, 0xe3}; // "nop"
|
||||
patch((void *) 0x4a038, nop_patch);
|
||||
}
|
||||
|
||||
// Disable Block Tinting
|
||||
|
@ -97,6 +97,8 @@ set(SRC
|
||||
src/level/DistanceChunkSorter.def
|
||||
src/level/renderer/Chunk.def
|
||||
src/level/LevelStorage.def
|
||||
src/level/BiomeSource.def
|
||||
src/level/Region.def
|
||||
src/item/ItemRenderer.def
|
||||
src/item/ItemInHandRenderer.def
|
||||
src/item/AuxDataTileItem.def
|
||||
|
9
symbols/src/level/BiomeSource.def
Normal file
9
symbols/src/level/BiomeSource.def
Normal file
@ -0,0 +1,9 @@
|
||||
static-property float tempScale = 0x110254;
|
||||
static-property float downfallScale = 0x110250;
|
||||
|
||||
vtable 0x110218;
|
||||
|
||||
virtual-method Biome **getBiomeBlock(int x, int z, int param_1, int param_2) = 0x14;
|
||||
|
||||
property float *temperature = 0x4;
|
||||
property float *downfall = 0x8;
|
@ -50,6 +50,7 @@ method bool getDirectSignal(int x, int y, int z, int direction) = 0xa5d2c;
|
||||
method bool canSeeSky(int x, int y, int z) = 0xa39b8;
|
||||
method bool isDay() = 0xa3d9c;
|
||||
method int getTopTile(int x, int z) = 0xa2cc8;
|
||||
method BiomeSource *getBiomeSource() = 0xa3c64;
|
||||
|
||||
virtual-method void tick() = 0x28;
|
||||
virtual-method void updateSleepingPlayerList() = 0x2c;
|
||||
|
5
symbols/src/level/Region.def
Normal file
5
symbols/src/level/Region.def
Normal file
@ -0,0 +1,5 @@
|
||||
extends LevelSource;
|
||||
|
||||
vtable 0x10ff58;
|
||||
|
||||
property Level *level = 0x10;
|
@ -57,6 +57,7 @@ virtual-method Tile *setExplodeable(float explodeable) = 0xf4;
|
||||
virtual-method Tile *setDestroyTime(float destroy_time) = 0xf8;
|
||||
virtual-method void spawnResources(Level *level, int x, int y, int z, int data, float chance) = 0x80;
|
||||
virtual-method Tile *setLightBlock(int strength) = 0xec;
|
||||
virtual-method bool shouldRenderFace(LevelSource *level_source, int x, int y, int z, int face) = 0x24;
|
||||
|
||||
property int texture = 0x4;
|
||||
property int id = 0x8;
|
||||
|
Loading…
Reference in New Issue
Block a user