mirror of
https://github.com/celisej567/mcpe.git
synced 2026-09-17 20:10:23 +03:00
* Add PatchManager - Allows you to patch terrain.png and items.png on the fly.
This can be used for modding, since you don't need to share copyrighted Mojang assets alongside your texture patches.
This commit is contained in:
@@ -126,3 +126,8 @@ bool AppPlatform::shiftPressed()
|
||||
void AppPlatform::setOptionStrings(const std::vector<std::string>& vec)
|
||||
{
|
||||
}
|
||||
|
||||
std::string AppPlatform::getPatchData()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -52,6 +52,8 @@ public:
|
||||
virtual bool shiftPressed();
|
||||
// Also add this to allow option saving.
|
||||
virtual void setOptionStrings(const std::vector<std::string>& vec);
|
||||
// Also add this to allow dynamic patching.
|
||||
virtual std::string getPatchData();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
#include "client/player/input/ControllerTurnInput.hpp"
|
||||
#endif
|
||||
|
||||
// custom:
|
||||
#include "client/renderer/PatchManager.hpp"
|
||||
|
||||
// note: Nothing changes these, so it'll think we're always running at 854x480 even if not
|
||||
int Minecraft::width = C_DEFAULT_SCREEN_WIDTH;
|
||||
int Minecraft::height = C_DEFAULT_SCREEN_HEIGHT;
|
||||
@@ -684,6 +687,14 @@ void Minecraft::init()
|
||||
reloadOptions();
|
||||
|
||||
m_pFont = new Font(&m_options, "font/default.png", m_pTextures);
|
||||
|
||||
// Patch Manager
|
||||
GetPatchManager()->LoadPatchData(platform()->getPatchData());
|
||||
|
||||
m_pTextures->loadAndBindTexture(C_TERRAIN_NAME);
|
||||
GetPatchManager()->PatchTextures(platform(), TYPE_TERRAIN);
|
||||
m_pTextures->loadAndBindTexture(C_ITEMS_NAME);
|
||||
GetPatchManager()->PatchTextures(platform(), TYPE_ITEMS);
|
||||
}
|
||||
|
||||
Minecraft::~Minecraft()
|
||||
|
||||
136
source/client/renderer/PatchManager.cpp
Normal file
136
source/client/renderer/PatchManager.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
#include "PatchManager.hpp"
|
||||
#include "AppPlatform.hpp"
|
||||
#include "client/common/Utils.hpp"
|
||||
#include "compat/GL.hpp"
|
||||
|
||||
#define PM_SEPARATOR ('|')
|
||||
|
||||
PatchManager* g_pPatchManager;
|
||||
PatchManager* GetPatchManager()
|
||||
{
|
||||
if (!g_pPatchManager)
|
||||
g_pPatchManager = new PatchManager;
|
||||
|
||||
return g_pPatchManager;
|
||||
}
|
||||
|
||||
PatchManager::PatchManager()
|
||||
{
|
||||
m_bGrassTinted = true;
|
||||
m_nMetalSideYOffset = -1;
|
||||
}
|
||||
|
||||
void PatchManager::LoadPatchData(const std::string& patchData)
|
||||
{
|
||||
std::stringstream patchDataStream(patchData);
|
||||
std::string currLine;
|
||||
|
||||
while (std::getline(patchDataStream, currLine))
|
||||
{
|
||||
if (currLine.empty()) continue;
|
||||
if (currLine[0] == '#') continue;
|
||||
|
||||
std::string command;
|
||||
std::stringstream lineStream(currLine);
|
||||
// read command type
|
||||
if (!std::getline(lineStream, command, PM_SEPARATOR))
|
||||
continue;
|
||||
|
||||
if (command == "terrain" || command == "items")
|
||||
{
|
||||
bool bIsItems = command == "items";
|
||||
std::string xStr, yStr, fileName;
|
||||
|
||||
if (!std::getline(lineStream, xStr, PM_SEPARATOR)) continue;
|
||||
if (!std::getline(lineStream, yStr, PM_SEPARATOR)) continue;
|
||||
if (!std::getline(lineStream, fileName, PM_SEPARATOR)) continue;
|
||||
|
||||
// turn the xStr and yStr into ints.
|
||||
int x, y;
|
||||
if (!sscanf(xStr.c_str(), "%d", &x)) continue;
|
||||
if (!sscanf(yStr.c_str(), "%d", &y)) continue;
|
||||
|
||||
m_patchData.push_back(PatchData(bIsItems ? TYPE_ITEMS : TYPE_TERRAIN, x, y, fileName));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// features -- TODO un-hardcode this
|
||||
if (command == "vegetation_tint")
|
||||
{
|
||||
ReadBool(lineStream, m_bGrassTinted);
|
||||
continue;
|
||||
}
|
||||
|
||||
// features -- TODO un-hardcode this
|
||||
if (command == "metal_block_sides")
|
||||
{
|
||||
ReadInt(lineStream, m_nMetalSideYOffset);
|
||||
continue;
|
||||
}
|
||||
|
||||
LogMsg("Unknown command %s from patch data.", command.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void PatchManager::PatchTextures(AppPlatform* pAppPlatform, ePatchType patchType)
|
||||
{
|
||||
// Use glTexSubImage2D to patch the terrain.png texture on the fly.
|
||||
for (int i = 0; i < int(m_patchData.size()); i++)
|
||||
{
|
||||
PatchData& pd = m_patchData[i];
|
||||
if (pd.m_type != patchType)
|
||||
continue;
|
||||
|
||||
Texture texture = pAppPlatform->loadTexture("patches/" + pd.m_filename, true);
|
||||
if (texture.m_width == 0)
|
||||
{
|
||||
LogMsg("Image %s has width 0, not found?! Skipping", pd.m_filename.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
glTexSubImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
pd.m_destX,
|
||||
pd.m_destY,
|
||||
texture.m_width,
|
||||
texture.m_height,
|
||||
GL_RGBA,
|
||||
GL_UNSIGNED_BYTE,
|
||||
texture.m_pixels
|
||||
);
|
||||
|
||||
SAFE_DELETE_ARRAY(texture.m_pixels);
|
||||
}
|
||||
}
|
||||
|
||||
bool PatchManager::IsGrassTinted()
|
||||
{
|
||||
return m_bGrassTinted;
|
||||
}
|
||||
|
||||
int PatchManager::GetMetalSideYOffset()
|
||||
{
|
||||
return m_nMetalSideYOffset;
|
||||
}
|
||||
|
||||
void PatchManager::ReadBool(std::istream& is, bool& b)
|
||||
{
|
||||
std::string flag;
|
||||
if (!std::getline(is, flag, PM_SEPARATOR))
|
||||
return;
|
||||
|
||||
b = (flag == "true" || flag == "1" || flag == "TRUE");
|
||||
}
|
||||
|
||||
void PatchManager::ReadInt(std::istream& is, int& i)
|
||||
{
|
||||
std::string flag;
|
||||
if (!std::getline(is, flag, PM_SEPARATOR))
|
||||
return;
|
||||
|
||||
int x = -1;
|
||||
if (sscanf(flag.c_str(), "%d", &x))
|
||||
i = x;
|
||||
}
|
||||
80
source/client/renderer/PatchManager.hpp
Normal file
80
source/client/renderer/PatchManager.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
class AppPlatform;
|
||||
|
||||
enum ePatchType
|
||||
{
|
||||
TYPE_NONE,
|
||||
TYPE_TERRAIN,
|
||||
TYPE_ITEMS,
|
||||
TYPE_FEATURE,
|
||||
};
|
||||
|
||||
enum ePatchOption
|
||||
{
|
||||
PO_NONE,
|
||||
PO_GRASS_TINT,
|
||||
};
|
||||
|
||||
struct PatchData
|
||||
{
|
||||
ePatchType m_type;
|
||||
ePatchOption m_option;
|
||||
int m_destX, m_destY;
|
||||
std::string m_filename;
|
||||
bool m_bEnable;
|
||||
|
||||
PatchData(ePatchType type, int x, int y, const std::string& fn)
|
||||
{
|
||||
_init();
|
||||
m_type = type;
|
||||
m_destX = x * 16;
|
||||
m_destY = y * 16;
|
||||
m_filename = fn;
|
||||
}
|
||||
|
||||
PatchData(ePatchType type, ePatchOption opt, bool enable)
|
||||
{
|
||||
_init();
|
||||
m_type = type;
|
||||
m_option = opt;
|
||||
m_bEnable = enable;
|
||||
}
|
||||
|
||||
void _init()
|
||||
{
|
||||
m_type = TYPE_NONE;
|
||||
m_option = PO_NONE;
|
||||
m_destX = m_destY = 0;
|
||||
m_bEnable = false;
|
||||
}
|
||||
};
|
||||
|
||||
class PatchManager
|
||||
{
|
||||
public:
|
||||
PatchManager();
|
||||
|
||||
void LoadPatchData(const std::string& patchData);
|
||||
|
||||
void PatchTextures(AppPlatform*, ePatchType);
|
||||
|
||||
// Features
|
||||
bool IsGrassTinted();
|
||||
int GetMetalSideYOffset();
|
||||
|
||||
private:
|
||||
void ReadBool(std::istream& is, bool& b);
|
||||
void ReadInt(std::istream& is, int& b);
|
||||
|
||||
private:
|
||||
bool m_bGrassTinted;
|
||||
int m_nMetalSideYOffset;
|
||||
std::vector<PatchData> m_patchData;
|
||||
};
|
||||
|
||||
PatchManager* GetPatchManager();
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "Tile.hpp"
|
||||
#include "world/level/Level.hpp"
|
||||
#include "client/renderer/PatchManager.hpp"
|
||||
|
||||
GrassTile::GrassTile(int id, Material* c) : Tile(id, c)
|
||||
{
|
||||
@@ -17,10 +18,10 @@ GrassTile::GrassTile(int id, Material* c) : Tile(id, c)
|
||||
|
||||
int GrassTile::getColor(LevelSource*, int x, int y, int z)
|
||||
{
|
||||
#ifdef MOD_DONT_COLOR_GRASS
|
||||
if (GetPatchManager()->IsGrassTinted())
|
||||
return 0x339933;
|
||||
|
||||
return 0xffffff;
|
||||
#endif
|
||||
return 0x339933;
|
||||
}
|
||||
|
||||
int GrassTile::getResource(int i, Random* random)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "Tile.hpp"
|
||||
#include "world/level/Level.hpp"
|
||||
#include "client/renderer/PatchManager.hpp"
|
||||
|
||||
LeafTile::LeafTile(int id) : TransparentTile(id, TEXTURE_LEAVES_TRANSPARENT, Material::leaves, false)
|
||||
{
|
||||
@@ -33,10 +34,10 @@ void LeafTile::die(Level* level, int x, int y, int z)
|
||||
|
||||
int LeafTile::getColor(LevelSource* level, int x, int y, int z)
|
||||
{
|
||||
#ifdef MOD_DONT_COLOR_GRASS
|
||||
if (GetPatchManager()->IsGrassTinted())
|
||||
return 0x339933;
|
||||
|
||||
return 0xffffff;
|
||||
#endif
|
||||
return 0x339933;
|
||||
}
|
||||
|
||||
int LeafTile::getTexture(int dir, int data)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "Tile.hpp"
|
||||
#include "world/level/Level.hpp"
|
||||
#include "client/renderer/PatchManager.hpp"
|
||||
|
||||
MetalTile::MetalTile(int ID, int texture, Material* pMtl) : Tile(ID, pMtl)
|
||||
{
|
||||
@@ -19,5 +20,12 @@ MetalTile::MetalTile(int ID, int texture, Material* pMtl) : Tile(ID, pMtl)
|
||||
// textures for these tiles. :)
|
||||
int MetalTile::getTexture(int dir)
|
||||
{
|
||||
return m_TextureFrame;
|
||||
int yoff = GetPatchManager()->GetMetalSideYOffset();
|
||||
if (yoff < 0)
|
||||
return m_TextureFrame;
|
||||
|
||||
if (dir == DIR_YPOS) return m_TextureFrame;
|
||||
if (dir == DIR_YNEG) return m_TextureFrame + 16 * (yoff + 1);
|
||||
|
||||
return m_TextureFrame + 16 * (yoff + 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user