mirror of
https://github.com/minetest/minetest.git
synced 2024-11-23 16:13:46 +01:00
Now texture handling is fast. Also now players are saved on disk.
This commit is contained in:
parent
bd100c5483
commit
64b5975732
BIN
data/grass.png
BIN
data/grass.png
Binary file not shown.
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
@ -271,6 +271,10 @@
|
|||||||
RelativePath=".\src\materials.cpp"
|
RelativePath=".\src\materials.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\mineral.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\player.cpp"
|
RelativePath=".\src\player.cpp"
|
||||||
>
|
>
|
||||||
|
@ -38,18 +38,12 @@ configure_file(
|
|||||||
"${PROJECT_BINARY_DIR}/cmake_config.h"
|
"${PROJECT_BINARY_DIR}/cmake_config.h"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(minetest_SRCS
|
set(common_SRCS
|
||||||
guiMainMenu.cpp
|
mineral.cpp
|
||||||
porting.cpp
|
porting.cpp
|
||||||
guiMessageMenu.cpp
|
|
||||||
materials.cpp
|
materials.cpp
|
||||||
guiTextInputMenu.cpp
|
|
||||||
guiInventoryMenu.cpp
|
|
||||||
irrlichtwrapper.cpp
|
|
||||||
guiPauseMenu.cpp
|
|
||||||
defaultsettings.cpp
|
defaultsettings.cpp
|
||||||
mapnode.cpp
|
mapnode.cpp
|
||||||
tile.cpp
|
|
||||||
voxel.cpp
|
voxel.cpp
|
||||||
mapblockobject.cpp
|
mapblockobject.cpp
|
||||||
inventory.cpp
|
inventory.cpp
|
||||||
@ -59,7 +53,6 @@ set(minetest_SRCS
|
|||||||
filesys.cpp
|
filesys.cpp
|
||||||
connection.cpp
|
connection.cpp
|
||||||
environment.cpp
|
environment.cpp
|
||||||
client.cpp
|
|
||||||
server.cpp
|
server.cpp
|
||||||
socket.cpp
|
socket.cpp
|
||||||
mapblock.cpp
|
mapblock.cpp
|
||||||
@ -68,34 +61,24 @@ set(minetest_SRCS
|
|||||||
map.cpp
|
map.cpp
|
||||||
player.cpp
|
player.cpp
|
||||||
utility.cpp
|
utility.cpp
|
||||||
main.cpp
|
|
||||||
test.cpp
|
test.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(minetest_SRCS
|
||||||
|
${common_SRCS}
|
||||||
|
guiMainMenu.cpp
|
||||||
|
guiMessageMenu.cpp
|
||||||
|
guiTextInputMenu.cpp
|
||||||
|
guiInventoryMenu.cpp
|
||||||
|
guiPauseMenu.cpp
|
||||||
|
irrlichtwrapper.cpp
|
||||||
|
client.cpp
|
||||||
|
main.cpp
|
||||||
|
)
|
||||||
|
|
||||||
set(minetestserver_SRCS
|
set(minetestserver_SRCS
|
||||||
porting.cpp
|
${common_SRCS}
|
||||||
materials.cpp
|
|
||||||
defaultsettings.cpp
|
|
||||||
mapnode.cpp
|
|
||||||
voxel.cpp
|
|
||||||
mapblockobject.cpp
|
|
||||||
inventory.cpp
|
|
||||||
debug.cpp
|
|
||||||
serialization.cpp
|
|
||||||
light.cpp
|
|
||||||
filesys.cpp
|
|
||||||
connection.cpp
|
|
||||||
environment.cpp
|
|
||||||
server.cpp
|
|
||||||
socket.cpp
|
|
||||||
mapblock.cpp
|
|
||||||
mapsector.cpp
|
|
||||||
heightmap.cpp
|
|
||||||
map.cpp
|
|
||||||
player.cpp
|
|
||||||
utility.cpp
|
|
||||||
servermain.cpp
|
servermain.cpp
|
||||||
test.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
|
@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
|
#include "filesys.h"
|
||||||
|
|
||||||
Environment::Environment(Map *map, std::ostream &dout):
|
Environment::Environment(Map *map, std::ostream &dout):
|
||||||
m_dout(dout)
|
m_dout(dout)
|
||||||
@ -192,6 +193,7 @@ void Environment::addPlayer(Player *player)
|
|||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
/*
|
/*
|
||||||
Check that only one local player exists and peer_ids are unique.
|
Check that only one local player exists and peer_ids are unique.
|
||||||
|
Also check that names are unique.
|
||||||
Exception: there can be multiple players with peer_id=0
|
Exception: there can be multiple players with peer_id=0
|
||||||
*/
|
*/
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
@ -201,8 +203,12 @@ void Environment::addPlayer(Player *player)
|
|||||||
*/
|
*/
|
||||||
assert(!(player->isLocal() == true && getLocalPlayer() != NULL));
|
assert(!(player->isLocal() == true && getLocalPlayer() != NULL));
|
||||||
#endif
|
#endif
|
||||||
|
// If peer id is non-zero, it has to be unique.
|
||||||
if(player->peer_id != 0)
|
if(player->peer_id != 0)
|
||||||
assert(getPlayer(player->peer_id) == NULL);
|
assert(getPlayer(player->peer_id) == NULL);
|
||||||
|
// Name has to be unique.
|
||||||
|
assert(getPlayer(player->getName()) == NULL);
|
||||||
|
// Add.
|
||||||
m_players.push_back(player);
|
m_players.push_back(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,6 +306,181 @@ void Environment::printPlayers(std::ostream &o)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Environment::serializePlayers(const std::string &savedir)
|
||||||
|
{
|
||||||
|
std::string players_path = savedir + "/players";
|
||||||
|
fs::CreateDir(players_path);
|
||||||
|
|
||||||
|
core::map<Player*, bool> saved_players;
|
||||||
|
|
||||||
|
std::vector<fs::DirListNode> player_files = fs::GetDirListing(players_path);
|
||||||
|
for(u32 i=0; i<player_files.size(); i++)
|
||||||
|
{
|
||||||
|
if(player_files[i].dir)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Full path to this file
|
||||||
|
std::string path = players_path + "/" + player_files[i].name;
|
||||||
|
|
||||||
|
dstream<<"Checking player file "<<path<<std::endl;
|
||||||
|
|
||||||
|
// Load player to see what is its name
|
||||||
|
ServerRemotePlayer testplayer;
|
||||||
|
{
|
||||||
|
// Open file and deserialize
|
||||||
|
std::ifstream is(path.c_str(), std::ios_base::binary);
|
||||||
|
if(is.good() == false)
|
||||||
|
{
|
||||||
|
dstream<<"Failed to read "<<path<<std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
testplayer.deSerialize(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
dstream<<"Loaded test player with name "<<testplayer.getName()<<std::endl;
|
||||||
|
|
||||||
|
// Search for the player
|
||||||
|
std::string playername = testplayer.getName();
|
||||||
|
Player *player = getPlayer(playername.c_str());
|
||||||
|
if(player == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"Didn't find matching player, ignoring file."<<std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dstream<<"Found matching player, overwriting."<<std::endl;
|
||||||
|
|
||||||
|
// OK, found. Save player there.
|
||||||
|
{
|
||||||
|
// Open file and serialize
|
||||||
|
std::ofstream os(path.c_str(), std::ios_base::binary);
|
||||||
|
if(os.good() == false)
|
||||||
|
{
|
||||||
|
dstream<<"Failed to overwrite "<<path<<std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
player->serialize(os);
|
||||||
|
saved_players.insert(player, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(core::list<Player*>::Iterator i = m_players.begin();
|
||||||
|
i != m_players.end(); i++)
|
||||||
|
{
|
||||||
|
Player *player = *i;
|
||||||
|
if(saved_players.find(player) != NULL)
|
||||||
|
{
|
||||||
|
dstream<<"Player "<<player->getName()
|
||||||
|
<<" was already saved."<<std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string playername = player->getName();
|
||||||
|
// Don't save unnamed player
|
||||||
|
if(playername == "")
|
||||||
|
{
|
||||||
|
dstream<<"Not saving unnamed player."<<std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Find a sane filename
|
||||||
|
*/
|
||||||
|
if(string_allowed(playername, PLAYERNAME_ALLOWED_CHARS) == false)
|
||||||
|
playername = "player";
|
||||||
|
std::string path = players_path + "/" + playername;
|
||||||
|
bool found = false;
|
||||||
|
for(u32 i=0; i<1000; i++)
|
||||||
|
{
|
||||||
|
if(fs::PathExists(path) == false)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
path = players_path + "/" + playername + itos(i);
|
||||||
|
}
|
||||||
|
if(found == false)
|
||||||
|
{
|
||||||
|
dstream<<"Didn't find free file for player"<<std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
dstream<<"Saving player "<<player->getName()<<" to "
|
||||||
|
<<path<<std::endl;
|
||||||
|
// Open file and serialize
|
||||||
|
std::ofstream os(path.c_str(), std::ios_base::binary);
|
||||||
|
if(os.good() == false)
|
||||||
|
{
|
||||||
|
dstream<<"Failed to overwrite "<<path<<std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
player->serialize(os);
|
||||||
|
saved_players.insert(player, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Environment::deSerializePlayers(const std::string &savedir)
|
||||||
|
{
|
||||||
|
std::string players_path = savedir + "/players";
|
||||||
|
|
||||||
|
core::map<Player*, bool> saved_players;
|
||||||
|
|
||||||
|
std::vector<fs::DirListNode> player_files = fs::GetDirListing(players_path);
|
||||||
|
for(u32 i=0; i<player_files.size(); i++)
|
||||||
|
{
|
||||||
|
if(player_files[i].dir)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Full path to this file
|
||||||
|
std::string path = players_path + "/" + player_files[i].name;
|
||||||
|
|
||||||
|
dstream<<"Checking player file "<<path<<std::endl;
|
||||||
|
|
||||||
|
// Load player to see what is its name
|
||||||
|
ServerRemotePlayer testplayer;
|
||||||
|
{
|
||||||
|
// Open file and deserialize
|
||||||
|
std::ifstream is(path.c_str(), std::ios_base::binary);
|
||||||
|
if(is.good() == false)
|
||||||
|
{
|
||||||
|
dstream<<"Failed to read "<<path<<std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
testplayer.deSerialize(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
dstream<<"Loaded test player with name "<<testplayer.getName()<<std::endl;
|
||||||
|
|
||||||
|
// Search for the player
|
||||||
|
std::string playername = testplayer.getName();
|
||||||
|
Player *player = getPlayer(playername.c_str());
|
||||||
|
bool newplayer = false;
|
||||||
|
if(player == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"Is a new player"<<std::endl;
|
||||||
|
player = new ServerRemotePlayer();
|
||||||
|
newplayer = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load player
|
||||||
|
{
|
||||||
|
dstream<<"Reading player "<<testplayer.getName()<<" from "
|
||||||
|
<<path<<std::endl;
|
||||||
|
// Open file and deserialize
|
||||||
|
std::ifstream is(path.c_str(), std::ios_base::binary);
|
||||||
|
if(is.good() == false)
|
||||||
|
{
|
||||||
|
dstream<<"Failed to read "<<path<<std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
player->deSerialize(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(newplayer)
|
||||||
|
addPlayer(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
void Environment::updateMeshes(v3s16 blockpos)
|
void Environment::updateMeshes(v3s16 blockpos)
|
||||||
{
|
{
|
||||||
|
@ -63,6 +63,10 @@ public:
|
|||||||
core::list<Player*> getPlayers();
|
core::list<Player*> getPlayers();
|
||||||
core::list<Player*> getPlayers(bool ignore_disconnected);
|
core::list<Player*> getPlayers(bool ignore_disconnected);
|
||||||
void printPlayers(std::ostream &o);
|
void printPlayers(std::ostream &o);
|
||||||
|
|
||||||
|
void serializePlayers(const std::string &savedir);
|
||||||
|
// This loads players as ServerRemotePlayers
|
||||||
|
void deSerializePlayers(const std::string &savedir);
|
||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
void updateMeshes(v3s16 blockpos);
|
void updateMeshes(v3s16 blockpos);
|
||||||
|
@ -217,7 +217,7 @@ void InventoryList::serialize(std::ostream &os)
|
|||||||
os<<"\n";
|
os<<"\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
os<<"end\n";
|
os<<"EndInventoryList\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryList::deSerialize(std::istream &is)
|
void InventoryList::deSerialize(std::istream &is)
|
||||||
@ -238,7 +238,7 @@ void InventoryList::deSerialize(std::istream &is)
|
|||||||
std::string name;
|
std::string name;
|
||||||
std::getline(iss, name, ' ');
|
std::getline(iss, name, ' ');
|
||||||
|
|
||||||
if(name == "end")
|
if(name == "EndInventoryList")
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -497,7 +497,7 @@ void Inventory::serialize(std::ostream &os)
|
|||||||
list->serialize(os);
|
list->serialize(os);
|
||||||
}
|
}
|
||||||
|
|
||||||
os<<"end\n";
|
os<<"EndInventory\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inventory::deSerialize(std::istream &is)
|
void Inventory::deSerialize(std::istream &is)
|
||||||
@ -514,7 +514,7 @@ void Inventory::deSerialize(std::istream &is)
|
|||||||
std::string name;
|
std::string name;
|
||||||
std::getline(iss, name, ' ');
|
std::getline(iss, name, ' ');
|
||||||
|
|
||||||
if(name == "end")
|
if(name == "EndInventory")
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -122,10 +122,12 @@ public:
|
|||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
video::ITexture * getImage()
|
video::ITexture * getImage()
|
||||||
{
|
{
|
||||||
if(m_content >= USEFUL_CONTENT_COUNT)
|
/*if(m_content >= USEFUL_CONTENT_COUNT)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return g_irrlicht->getTexture(g_content_inventory_texture_paths[m_content]);
|
return g_irrlicht->getTexture(g_content_inventory_texture_paths[m_content]);*/
|
||||||
|
|
||||||
|
return g_irrlicht->getTexture(content_features(m_content).inventory_texture);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
std::string getText()
|
std::string getText()
|
||||||
@ -250,19 +252,19 @@ public:
|
|||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
video::ITexture * getImage()
|
video::ITexture * getImage()
|
||||||
{
|
{
|
||||||
std::string basename;
|
std::string name;
|
||||||
|
|
||||||
if(m_subname == "Stick")
|
if(m_subname == "Stick")
|
||||||
basename = porting::getDataPath("stick.png");
|
name = "stick.png";
|
||||||
else if(m_subname == "lump_of_coal")
|
else if(m_subname == "lump_of_coal")
|
||||||
basename = porting::getDataPath("lump_of_coal.png");
|
name = "lump_of_coal.png";
|
||||||
else if(m_subname == "lump_of_iron")
|
else if(m_subname == "lump_of_iron")
|
||||||
basename = porting::getDataPath("lump_of_iron.png");
|
name = "lump_of_iron.png";
|
||||||
else
|
else
|
||||||
basename = porting::getDataPath("cloud.png[[mod:crack3");
|
name = "cloud.png";
|
||||||
|
|
||||||
// Get such a texture
|
// Get such a texture
|
||||||
return g_irrlicht->getTexture(basename);
|
return g_irrlicht->getTexture(name);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
std::string getText()
|
std::string getText()
|
||||||
@ -330,28 +332,35 @@ public:
|
|||||||
{
|
{
|
||||||
std::string basename;
|
std::string basename;
|
||||||
if(m_toolname == "WPick")
|
if(m_toolname == "WPick")
|
||||||
basename = porting::getDataPath("tool_wpick.png").c_str();
|
basename = "tool_wpick.png";
|
||||||
else if(m_toolname == "STPick")
|
else if(m_toolname == "STPick")
|
||||||
basename = porting::getDataPath("tool_stpick.png").c_str();
|
basename = "tool_stpick.png";
|
||||||
else if(m_toolname == "MesePick")
|
else if(m_toolname == "MesePick")
|
||||||
basename = porting::getDataPath("tool_mesepick.png").c_str();
|
basename = "tool_mesepick.png";
|
||||||
// Default to cloud texture
|
|
||||||
else
|
else
|
||||||
basename = porting::getDataPath("cloud.png").c_str();
|
basename = "cloud.png";
|
||||||
//basename = tile_texture_path_get(TILE_CLOUD);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Calculate some progress value with sane amount of
|
Calculate a progress value with sane amount of
|
||||||
maximum states
|
maximum states
|
||||||
*/
|
*/
|
||||||
u32 maxprogress = 30;
|
u32 maxprogress = 30;
|
||||||
u32 toolprogress = (65535-m_wear)/(65535/maxprogress);
|
u32 toolprogress = (65535-m_wear)/(65535/maxprogress);
|
||||||
|
|
||||||
// Make texture name for the new texture with a progress bar
|
float value_f = (float)toolprogress / (float)maxprogress;
|
||||||
|
std::ostringstream os;
|
||||||
|
os<<"[progressbar"<<value_f;
|
||||||
|
|
||||||
|
TextureSpec spec;
|
||||||
|
spec.addTid(g_irrlicht->getTextureId(basename));
|
||||||
|
spec.addTid(g_irrlicht->getTextureId(os.str()));
|
||||||
|
return g_irrlicht->getTexture(spec);
|
||||||
|
|
||||||
|
/*// Make texture name for the new texture with a progress bar
|
||||||
float value_f = (float)toolprogress / (float)maxprogress;
|
float value_f = (float)toolprogress / (float)maxprogress;
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os<<basename<<"[[mod:progressbar"<<value_f;
|
os<<basename<<"[[mod:progressbar"<<value_f;
|
||||||
return g_irrlicht->getTexture(os.str());
|
return g_irrlicht->getTexture(os.str());*/
|
||||||
|
|
||||||
/*// Make texture name for the new texture with a progress bar
|
/*// Make texture name for the new texture with a progress bar
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
|
@ -17,13 +17,15 @@ void IrrlichtWrapper::Run()
|
|||||||
*/
|
*/
|
||||||
if(m_get_texture_queue.size() > 0)
|
if(m_get_texture_queue.size() > 0)
|
||||||
{
|
{
|
||||||
GetRequest<std::string, video::ITexture*, u8, u8>
|
GetRequest<TextureSpec, video::ITexture*, u8, u8>
|
||||||
request = m_get_texture_queue.pop();
|
request = m_get_texture_queue.pop();
|
||||||
|
|
||||||
dstream<<"got texture request with key="
|
dstream<<"got texture request with"
|
||||||
<<request.key<<std::endl;
|
<<" key.tids[0]="<<request.key.tids[0]
|
||||||
|
<<" [1]="<<request.key.tids[1]
|
||||||
|
<<std::endl;
|
||||||
|
|
||||||
GetResult<std::string, video::ITexture*, u8, u8>
|
GetResult<TextureSpec, video::ITexture*, u8, u8>
|
||||||
result;
|
result;
|
||||||
result.key = request.key;
|
result.key = request.key;
|
||||||
result.callers = request.callers;
|
result.callers = request.callers;
|
||||||
@ -33,9 +35,29 @@ void IrrlichtWrapper::Run()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
video::ITexture* IrrlichtWrapper::getTexture(const std::string &spec)
|
textureid_t IrrlichtWrapper::getTextureId(const std::string &name)
|
||||||
{
|
{
|
||||||
if(spec == "")
|
u32 id = m_namecache.getId(name);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string IrrlichtWrapper::getTextureName(textureid_t id)
|
||||||
|
{
|
||||||
|
std::string name("");
|
||||||
|
m_namecache.getValue(id, name);
|
||||||
|
// In case it was found, return the name; otherwise return an empty name.
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
video::ITexture* IrrlichtWrapper::getTexture(const std::string &name)
|
||||||
|
{
|
||||||
|
TextureSpec spec(getTextureId(name));
|
||||||
|
return getTexture(spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
video::ITexture* IrrlichtWrapper::getTexture(const TextureSpec &spec)
|
||||||
|
{
|
||||||
|
if(spec.empty())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
video::ITexture *t = m_texturecache.get(spec);
|
video::ITexture *t = m_texturecache.get(spec);
|
||||||
@ -44,26 +66,26 @@ video::ITexture* IrrlichtWrapper::getTexture(const std::string &spec)
|
|||||||
|
|
||||||
if(get_current_thread_id() == m_main_thread)
|
if(get_current_thread_id() == m_main_thread)
|
||||||
{
|
{
|
||||||
dstream<<"Getting texture directly: spec="
|
dstream<<"Getting texture directly: spec.tids[0]="
|
||||||
<<spec<<std::endl;
|
<<spec.tids[0]<<std::endl;
|
||||||
|
|
||||||
t = getTextureDirect(spec);
|
t = getTextureDirect(spec);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We're gonna ask the result to be put into here
|
// We're gonna ask the result to be put into here
|
||||||
ResultQueue<std::string, video::ITexture*, u8, u8> result_queue;
|
ResultQueue<TextureSpec, video::ITexture*, u8, u8> result_queue;
|
||||||
|
|
||||||
// Throw a request in
|
// Throw a request in
|
||||||
m_get_texture_queue.add(spec, 0, 0, &result_queue);
|
m_get_texture_queue.add(spec, 0, 0, &result_queue);
|
||||||
|
|
||||||
dstream<<"Waiting for texture from main thread: "
|
dstream<<"Waiting for texture from main thread: spec.tids[0]="
|
||||||
<<spec<<std::endl;
|
<<spec.tids[0]<<std::endl;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Wait result for a second
|
// Wait result for a second
|
||||||
GetResult<std::string, video::ITexture*, u8, u8>
|
GetResult<TextureSpec, video::ITexture*, u8, u8>
|
||||||
result = result_queue.pop_front(1000);
|
result = result_queue.pop_front(1000);
|
||||||
|
|
||||||
// Check that at least something worked OK
|
// Check that at least something worked OK
|
||||||
@ -83,144 +105,177 @@ video::ITexture* IrrlichtWrapper::getTexture(const std::string &spec)
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Draw a progress bar on the image
|
||||||
Non-thread-safe functions
|
void make_progressbar(float value, video::IImage *image);
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Texture modifier functions
|
Texture fetcher/maker function, called always from the main thread
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// blitted_name = eg. "mineral_coal.png"
|
video::ITexture* IrrlichtWrapper::getTextureDirect(const TextureSpec &spec)
|
||||||
video::ITexture * make_blitname(const std::string &blitted_name,
|
|
||||||
video::ITexture *original,
|
|
||||||
const char *newname, video::IVideoDriver* driver)
|
|
||||||
{
|
{
|
||||||
if(original == NULL)
|
// This would result in NULL image
|
||||||
|
if(spec.empty())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// Size of the base image
|
// Don't generate existing stuff
|
||||||
core::dimension2d<u32> dim(16, 16);
|
video::ITexture *t = m_texturecache.get(spec);
|
||||||
// Position to copy the blitted to in the base image
|
if(t != NULL)
|
||||||
core::position2d<s32> pos_base(0, 0);
|
{
|
||||||
// Position to copy the blitted from in the blitted image
|
dstream<<"WARNING: Existing stuff requested from "
|
||||||
core::position2d<s32> pos_other(0, 0);
|
"getTextureDirect()"<<std::endl;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
video::IVideoDriver* driver = m_device->getVideoDriver();
|
||||||
|
|
||||||
video::IImage *baseimage = driver->createImage(original, pos_base, dim);
|
/*
|
||||||
assert(baseimage);
|
An image will be built from files and then converted into a texture.
|
||||||
|
*/
|
||||||
|
video::IImage *baseimg = NULL;
|
||||||
|
|
||||||
video::IImage *blittedimage = driver->createImageFromFile(porting::getDataPath(blitted_name.c_str()).c_str());
|
/*
|
||||||
assert(blittedimage);
|
Irrlicht requires a name for every texture, with which it
|
||||||
|
will be stored internally in irrlicht.
|
||||||
|
*/
|
||||||
|
std::string texture_name;
|
||||||
|
|
||||||
|
for(u32 i=0; i<TEXTURE_SPEC_TEXTURE_COUNT; i++)
|
||||||
|
{
|
||||||
|
textureid_t tid = spec.tids[i];
|
||||||
|
if(tid == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::string name = getTextureName(tid);
|
||||||
|
|
||||||
|
// Add something to the name so that it is a unique identifier.
|
||||||
|
texture_name += "[";
|
||||||
|
texture_name += name;
|
||||||
|
texture_name += "]";
|
||||||
|
|
||||||
|
if(name[0] != '[')
|
||||||
|
{
|
||||||
|
// A normal texture; load it from a file
|
||||||
|
std::string path = porting::getDataPath(name.c_str());
|
||||||
|
dstream<<"getTextureDirect(): Loading path \""<<path
|
||||||
|
<<"\""<<std::endl;
|
||||||
|
video::IImage *image = driver->createImageFromFile(path.c_str());
|
||||||
|
|
||||||
|
if(image == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: Could not load image \""<<name
|
||||||
|
<<"\" from path \""<<path<<"\""
|
||||||
|
<<" while building texture"<<std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If base image is NULL, load as base.
|
||||||
|
if(baseimg == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"Setting "<<name<<" as base"<<std::endl;
|
||||||
|
/*
|
||||||
|
Copy it this way to get an alpha channel.
|
||||||
|
Otherwise images with alpha cannot be blitted on
|
||||||
|
images that don't have alpha in the original file.
|
||||||
|
*/
|
||||||
|
// This is a deprecated method
|
||||||
|
//baseimg = driver->createImage(video::ECF_A8R8G8B8, image);
|
||||||
|
core::dimension2d<u32> dim = image->getDimension();
|
||||||
|
baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
|
||||||
|
image->copyTo(baseimg);
|
||||||
|
image->drop();
|
||||||
|
//baseimg = image;
|
||||||
|
}
|
||||||
|
// Else blit on base.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstream<<"Blitting "<<name<<" on base"<<std::endl;
|
||||||
|
// Size of the copied area
|
||||||
|
core::dimension2d<u32> dim = image->getDimension();
|
||||||
|
//core::dimension2d<u32> dim(16,16);
|
||||||
|
// Position to copy the blitted to in the base image
|
||||||
|
core::position2d<s32> pos_to(0,0);
|
||||||
|
// Position to copy the blitted from in the blitted image
|
||||||
|
core::position2d<s32> pos_from(0,0);
|
||||||
|
// Blit
|
||||||
|
image->copyToWithAlpha(baseimg, pos_to,
|
||||||
|
core::rect<s32>(pos_from, dim),
|
||||||
|
video::SColor(255,255,255,255),
|
||||||
|
NULL);
|
||||||
|
// Drop image
|
||||||
|
image->drop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// A special texture modification
|
||||||
|
dstream<<"getTextureDirect(): generating \""<<name<<"\""
|
||||||
|
<<std::endl;
|
||||||
|
if(name.substr(0,6) == "[crack")
|
||||||
|
{
|
||||||
|
u16 progression = stoi(name.substr(6));
|
||||||
|
// Size of the base image
|
||||||
|
core::dimension2d<u32> dim(16, 16);
|
||||||
|
// Size of the crack image
|
||||||
|
//core::dimension2d<u32> dim_crack(16, 16 * CRACK_ANIMATION_LENGTH);
|
||||||
|
// Position to copy the crack to in the base image
|
||||||
|
core::position2d<s32> pos_base(0, 0);
|
||||||
|
// Position to copy the crack from in the crack image
|
||||||
|
core::position2d<s32> pos_other(0, 16 * progression);
|
||||||
|
|
||||||
|
video::IImage *crackimage = driver->createImageFromFile(
|
||||||
|
porting::getDataPath("crack.png").c_str());
|
||||||
|
crackimage->copyToWithAlpha(baseimg, v2s32(0,0),
|
||||||
|
core::rect<s32>(pos_other, dim),
|
||||||
|
video::SColor(255,255,255,255),
|
||||||
|
NULL);
|
||||||
|
crackimage->drop();
|
||||||
|
}
|
||||||
|
else if(name.substr(0,12) == "[progressbar")
|
||||||
|
{
|
||||||
|
float value = stof(name.substr(12));
|
||||||
|
make_progressbar(value, baseimg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: getTextureDirect(): Invalid "
|
||||||
|
" texture: \""<<name<<"\""<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no resulting image, return NULL
|
||||||
|
if(baseimg == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"getTextureDirect(): baseimg is NULL (attempted to"
|
||||||
|
" create texture \""<<texture_name<<"\""<<std::endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Then copy the right part of blittedimage to baseimage
|
/*// DEBUG: Paint some pixels
|
||||||
|
video::SColor c(255,255,0,0);
|
||||||
blittedimage->copyToWithAlpha(baseimage, v2s32(0,0),
|
baseimg->setPixel(1,1, c);
|
||||||
core::rect<s32>(pos_other, dim),
|
baseimg->setPixel(1,14, c);
|
||||||
video::SColor(255,255,255,255),
|
baseimg->setPixel(14,1, c);
|
||||||
NULL);
|
baseimg->setPixel(14,14, c);*/
|
||||||
|
|
||||||
blittedimage->drop();
|
|
||||||
|
|
||||||
// Create texture from resulting image
|
// Create texture from resulting image
|
||||||
|
t = driver->addTexture(texture_name.c_str(), baseimg);
|
||||||
|
baseimg->drop();
|
||||||
|
|
||||||
video::ITexture *newtexture = driver->addTexture(newname, baseimage);
|
dstream<<"getTextureDirect(): created texture \""<<texture_name
|
||||||
|
<<"\""<<std::endl;
|
||||||
|
|
||||||
baseimage->drop();
|
return t;
|
||||||
|
|
||||||
return newtexture;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
video::ITexture * make_crack(u16 progression, video::ITexture *original,
|
void make_progressbar(float value, video::IImage *image)
|
||||||
const char *newname, video::IVideoDriver* driver)
|
|
||||||
{
|
{
|
||||||
if(original == NULL)
|
if(image == NULL)
|
||||||
return NULL;
|
return;
|
||||||
|
|
||||||
// Size of the base image
|
core::dimension2d<u32> size = image->getDimension();
|
||||||
core::dimension2d<u32> dim(16, 16);
|
|
||||||
// Size of the crack image
|
|
||||||
//core::dimension2d<u32> dim_crack(16, 16 * CRACK_ANIMATION_LENGTH);
|
|
||||||
// Position to copy the crack to in the base image
|
|
||||||
core::position2d<s32> pos_base(0, 0);
|
|
||||||
// Position to copy the crack from in the crack image
|
|
||||||
core::position2d<s32> pos_other(0, 16 * progression);
|
|
||||||
|
|
||||||
video::IImage *baseimage = driver->createImage(original, pos_base, dim);
|
|
||||||
assert(baseimage);
|
|
||||||
|
|
||||||
video::IImage *crackimage = driver->createImageFromFile(porting::getDataPath("crack.png").c_str());
|
|
||||||
assert(crackimage);
|
|
||||||
|
|
||||||
// Then copy the right part of crackimage to baseimage
|
|
||||||
|
|
||||||
crackimage->copyToWithAlpha(baseimage, v2s32(0,0),
|
|
||||||
core::rect<s32>(pos_other, dim),
|
|
||||||
video::SColor(255,255,255,255),
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
crackimage->drop();
|
|
||||||
|
|
||||||
// Create texture from resulting image
|
|
||||||
|
|
||||||
video::ITexture *newtexture = driver->addTexture(newname, baseimage);
|
|
||||||
|
|
||||||
baseimage->drop();
|
|
||||||
|
|
||||||
return newtexture;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
video::ITexture * make_sidegrass(video::ITexture *original,
|
|
||||||
const char *newname, video::IVideoDriver* driver)
|
|
||||||
{
|
|
||||||
if(original == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
// Size of the base image
|
|
||||||
core::dimension2d<u32> dim(16, 16);
|
|
||||||
// Position to copy the grass to in the base image
|
|
||||||
core::position2d<s32> pos_base(0, 0);
|
|
||||||
// Position to copy the grass from in the grass image
|
|
||||||
core::position2d<s32> pos_other(0, 0);
|
|
||||||
|
|
||||||
video::IImage *baseimage = driver->createImage(original, pos_base, dim);
|
|
||||||
assert(baseimage);
|
|
||||||
|
|
||||||
video::IImage *grassimage = driver->createImageFromFile(porting::getDataPath("grass_side.png").c_str());
|
|
||||||
assert(grassimage);
|
|
||||||
|
|
||||||
// Then copy the right part of grassimage to baseimage
|
|
||||||
|
|
||||||
grassimage->copyToWithAlpha(baseimage, v2s32(0,0),
|
|
||||||
core::rect<s32>(pos_other, dim),
|
|
||||||
video::SColor(255,255,255,255),
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
grassimage->drop();
|
|
||||||
|
|
||||||
// Create texture from resulting image
|
|
||||||
|
|
||||||
video::ITexture *newtexture = driver->addTexture(newname, baseimage);
|
|
||||||
|
|
||||||
baseimage->drop();
|
|
||||||
|
|
||||||
return newtexture;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
video::ITexture * make_progressbar(float value, video::ITexture *original,
|
|
||||||
const char *newname, video::IVideoDriver* driver)
|
|
||||||
{
|
|
||||||
if(original == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
core::position2d<s32> pos_base(0, 0);
|
|
||||||
core::dimension2d<u32> dim = original->getOriginalSize();
|
|
||||||
|
|
||||||
video::IImage *baseimage = driver->createImage(original, pos_base, dim);
|
|
||||||
assert(baseimage);
|
|
||||||
|
|
||||||
core::dimension2d<u32> size = baseimage->getDimension();
|
|
||||||
|
|
||||||
u32 barheight = 1;
|
u32 barheight = 1;
|
||||||
u32 barpad_x = 1;
|
u32 barpad_x = 1;
|
||||||
@ -242,177 +297,9 @@ video::ITexture * make_progressbar(float value, video::ITexture *original,
|
|||||||
u32 x = x0 + barpos.X;
|
u32 x = x0 + barpos.X;
|
||||||
for(u32 y=barpos.Y; y<barpos.Y+barheight; y++)
|
for(u32 y=barpos.Y; y<barpos.Y+barheight; y++)
|
||||||
{
|
{
|
||||||
baseimage->setPixel(x,y, *c);
|
image->setPixel(x,y, *c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
video::ITexture *newtexture = driver->addTexture(newname, baseimage);
|
|
||||||
|
|
||||||
baseimage->drop();
|
|
||||||
|
|
||||||
return newtexture;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Texture fetcher/maker function, called always from the main thread
|
|
||||||
*/
|
|
||||||
|
|
||||||
video::ITexture* IrrlichtWrapper::getTextureDirect(const std::string &spec)
|
|
||||||
{
|
|
||||||
if(spec == "")
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
video::IVideoDriver* driver = m_device->getVideoDriver();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Input (spec) is something like this:
|
|
||||||
"/usr/share/minetest/stone.png[[mod:mineral0[[mod:crack3"
|
|
||||||
*/
|
|
||||||
|
|
||||||
video::ITexture* t = NULL;
|
|
||||||
std::string modmagic = "[[mod:";
|
|
||||||
Strfnd f(spec);
|
|
||||||
std::string path = f.next(modmagic);
|
|
||||||
t = driver->getTexture(path.c_str());
|
|
||||||
std::string texture_name = path;
|
|
||||||
while(f.atend() == false)
|
|
||||||
{
|
|
||||||
std::string mod = f.next(modmagic);
|
|
||||||
texture_name += modmagic + mod;
|
|
||||||
dstream<<"Making texture \""<<texture_name<<"\""<<std::endl;
|
|
||||||
/*if(mod == "sidegrass")
|
|
||||||
{
|
|
||||||
t = make_sidegrass(t, texture_name.c_str(), driver);
|
|
||||||
}
|
|
||||||
else*/
|
|
||||||
if(mod.substr(0, 9) == "blitname:")
|
|
||||||
{
|
|
||||||
//t = make_sidegrass(t, texture_name.c_str(), driver);
|
|
||||||
t = make_blitname(mod.substr(9), t, texture_name.c_str(), driver);
|
|
||||||
}
|
|
||||||
else if(mod.substr(0,5) == "crack")
|
|
||||||
{
|
|
||||||
u16 prog = stoi(mod.substr(5));
|
|
||||||
t = make_crack(prog, t, texture_name.c_str(), driver);
|
|
||||||
}
|
|
||||||
else if(mod.substr(0,11) == "progressbar")
|
|
||||||
{
|
|
||||||
float value = stof(mod.substr(11));
|
|
||||||
t = make_progressbar(value, t, texture_name.c_str(), driver);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dstream<<"Invalid texture mod: \""<<mod<<"\""<<std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return t;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
video::ITexture* t = NULL;
|
|
||||||
const char *modmagic = "[[mod:";
|
|
||||||
const s32 modmagic_len = 6;
|
|
||||||
enum{
|
|
||||||
READMODE_PATH,
|
|
||||||
READMODE_MOD
|
|
||||||
} readmode = READMODE_PATH;
|
|
||||||
s32 specsize = spec.size()+1;
|
|
||||||
char *strcache = (char*)malloc(specsize);
|
|
||||||
assert(strcache);
|
|
||||||
char *path = NULL;
|
|
||||||
s32 length = 0;
|
|
||||||
// Next index of modmagic to be found
|
|
||||||
s32 modmagic_i = 0;
|
|
||||||
u32 i=0;
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
strcache[length++] = spec[i];
|
|
||||||
|
|
||||||
bool got_modmagic = false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check modmagic
|
|
||||||
*/
|
|
||||||
if(spec[i] == modmagic[modmagic_i])
|
|
||||||
{
|
|
||||||
modmagic_i++;
|
|
||||||
if(modmagic_i == modmagic_len)
|
|
||||||
{
|
|
||||||
got_modmagic = true;
|
|
||||||
modmagic_i = 0;
|
|
||||||
length -= modmagic_len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
modmagic_i = 0;
|
|
||||||
|
|
||||||
// Set i to be the length of read string
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if(got_modmagic || i >= spec.size())
|
|
||||||
{
|
|
||||||
strcache[length] = '\0';
|
|
||||||
// Now our string is in strcache, ending in \0
|
|
||||||
|
|
||||||
if(readmode == READMODE_PATH)
|
|
||||||
{
|
|
||||||
// Get initial texture (strcache is path)
|
|
||||||
assert(t == NULL);
|
|
||||||
t = driver->getTexture(strcache);
|
|
||||||
readmode = READMODE_MOD;
|
|
||||||
path = strcache;
|
|
||||||
strcache = (char*)malloc(specsize);
|
|
||||||
assert(strcache);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dstream<<"Parsing mod \""<<strcache<<"\""<<std::endl;
|
|
||||||
// The name of the result of adding this mod.
|
|
||||||
// This doesn't have to be fast so std::string is used.
|
|
||||||
std::string name(path);
|
|
||||||
name += "[[mod:";
|
|
||||||
name += strcache;
|
|
||||||
dstream<<"Name of modded texture is \""<<name<<"\""
|
|
||||||
<<std::endl;
|
|
||||||
// Sidegrass
|
|
||||||
if(strcmp(strcache, "sidegrass") == 0)
|
|
||||||
{
|
|
||||||
t = make_sidegrass(t, name.c_str(), driver);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dstream<<"Invalid texture mod"<<std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(i >= spec.size())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*if(spec.mod == NULL)
|
|
||||||
{
|
|
||||||
dstream<<"IrrlichtWrapper::getTextureDirect: Loading texture "
|
|
||||||
<<spec.path<<std::endl;
|
|
||||||
return driver->getTexture(spec.path.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
dstream<<"IrrlichtWrapper::getTextureDirect: Loading and modifying "
|
|
||||||
"texture "<<spec.path<<" to make "<<spec.name<<std::endl;
|
|
||||||
|
|
||||||
video::ITexture *base = driver->getTexture(spec.path.c_str());
|
|
||||||
video::ITexture *result = spec.mod->make(base, spec.name.c_str(), driver);
|
|
||||||
|
|
||||||
delete spec.mod;*/
|
|
||||||
|
|
||||||
if(strcache)
|
|
||||||
free(strcache);
|
|
||||||
if(path)
|
|
||||||
free(path);
|
|
||||||
|
|
||||||
return t;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
#include "texture.h"
|
||||||
|
|
||||||
#include <jmutex.h>
|
#include <jmutex.h>
|
||||||
#include <jmutexautolock.h>
|
#include <jmutexautolock.h>
|
||||||
@ -36,7 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
threads, because texture pointers have to be handled in
|
threads, because texture pointers have to be handled in
|
||||||
background threads.
|
background threads.
|
||||||
*/
|
*/
|
||||||
|
#if 0
|
||||||
class TextureCache
|
class TextureCache
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -73,12 +74,55 @@ private:
|
|||||||
core::map<std::string, video::ITexture*> m_textures;
|
core::map<std::string, video::ITexture*> m_textures;
|
||||||
JMutex m_mutex;
|
JMutex m_mutex;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
A thread-safe texture pointer cache
|
||||||
|
*/
|
||||||
|
class TextureCache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextureCache()
|
||||||
|
{
|
||||||
|
m_mutex.Init();
|
||||||
|
assert(m_mutex.IsInitialized());
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(const TextureSpec &spec, video::ITexture *texture)
|
||||||
|
{
|
||||||
|
if(texture == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
m_textures[spec] = texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
video::ITexture* get(const TextureSpec &spec)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
core::map<TextureSpec, video::ITexture*>::Node *n;
|
||||||
|
n = m_textures.find(spec);
|
||||||
|
|
||||||
|
if(n != NULL)
|
||||||
|
return n->getValue();
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
core::map<TextureSpec, video::ITexture*> m_textures;
|
||||||
|
JMutex m_mutex;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A thread-safe wrapper for irrlicht, to be accessed from
|
A thread-safe wrapper for irrlicht, to be accessed from
|
||||||
background worker threads.
|
background worker threads.
|
||||||
|
|
||||||
Queues tasks to be done in the main thread.
|
Queues tasks to be done in the main thread.
|
||||||
|
|
||||||
|
Also caches texture specification strings to ids and textures.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class IrrlichtWrapper
|
class IrrlichtWrapper
|
||||||
@ -103,30 +147,55 @@ public:
|
|||||||
return m_device->getTimer()->getRealTime();
|
return m_device->getTimer()->getRealTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Path can contain stuff like
|
Format of a texture name:
|
||||||
"/usr/share/minetest/stone.png[[mod:mineral0[[mod:crack3"
|
"stone.png" (filename in image data directory)
|
||||||
|
"[crack1" (a name starting with "[" is a special feature)
|
||||||
|
"[progress1.0" (a name starting with "[" is a special feature)
|
||||||
*/
|
*/
|
||||||
video::ITexture* getTexture(const std::string &spec);
|
/*
|
||||||
|
Loads texture defined by "name" and assigns a texture id to it.
|
||||||
|
If texture has to be generated, generates it.
|
||||||
|
If the texture has already been loaded, returns existing id.
|
||||||
|
*/
|
||||||
|
textureid_t getTextureId(const std::string &name);
|
||||||
|
// The reverse of the above
|
||||||
|
std::string getTextureName(textureid_t id);
|
||||||
|
// Gets a texture based on a filename
|
||||||
|
video::ITexture* getTexture(const std::string &name);
|
||||||
|
// Gets a texture based on a TextureSpec (a textureid_t is fine too)
|
||||||
|
video::ITexture* getTexture(const TextureSpec &spec);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*
|
/*
|
||||||
Non-thread-safe variants of stuff, for internal use
|
Non-thread-safe variants of stuff, for internal use
|
||||||
*/
|
*/
|
||||||
video::ITexture* getTextureDirect(const std::string &spec);
|
|
||||||
|
// DEPRECATED NO-OP
|
||||||
|
//video::ITexture* getTextureDirect(const std::string &spec);
|
||||||
|
|
||||||
|
// Constructs a texture according to spec
|
||||||
|
video::ITexture* getTextureDirect(const TextureSpec &spec);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Members
|
Members
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// The id of the thread that can (and has to) use irrlicht directly
|
||||||
threadid_t m_main_thread;
|
threadid_t m_main_thread;
|
||||||
|
|
||||||
|
// The irrlicht device
|
||||||
JMutex m_device_mutex;
|
JMutex m_device_mutex;
|
||||||
IrrlichtDevice *m_device;
|
IrrlichtDevice *m_device;
|
||||||
|
|
||||||
TextureCache m_texturecache;
|
|
||||||
|
|
||||||
RequestQueue<std::string, video::ITexture*, u8, u8> m_get_texture_queue;
|
// Queued texture fetches (to be processed by the main thread)
|
||||||
|
RequestQueue<TextureSpec, video::ITexture*, u8, u8> m_get_texture_queue;
|
||||||
|
|
||||||
|
// Cache of textures by spec
|
||||||
|
TextureCache m_texturecache;
|
||||||
|
|
||||||
|
// A mapping from texture id to string spec
|
||||||
|
MutexedIdGenerator<std::string> m_namecache;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
61
src/main.cpp
61
src/main.cpp
@ -104,8 +104,11 @@ SUGG: Meshes of blocks could be split into 6 meshes facing into
|
|||||||
Gaming ideas:
|
Gaming ideas:
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
- Aim for something like controlling a single dwarf in Dwarf Fortress.
|
- Aim for something like controlling a single dwarf in Dwarf Fortress
|
||||||
|
|
||||||
|
- The player could go faster by a crafting a boat, or riding an animal
|
||||||
|
|
||||||
|
- Random NPC traders. what else?
|
||||||
|
|
||||||
Documentation:
|
Documentation:
|
||||||
--------------
|
--------------
|
||||||
@ -165,6 +168,20 @@ TODO: Make fetching sector's blocks more efficient when rendering
|
|||||||
|
|
||||||
TODO: Flowing water animation
|
TODO: Flowing water animation
|
||||||
|
|
||||||
|
FIXME: The new texture stuff is slow on wine
|
||||||
|
- A basic grassy ground block takes 20-40ms
|
||||||
|
- A bit more complicated block can take 270ms
|
||||||
|
- On linux, a similar one doesn't take long at all (14ms)
|
||||||
|
- It is NOT a bad std::string implementation of MSVC.
|
||||||
|
- Can take up to 200ms? Is it when loading textures or always?
|
||||||
|
- Updating excess amount of meshes when making footprints is too
|
||||||
|
slow. It has to be fixed.
|
||||||
|
-> implement Map::updateNodeMeshes()
|
||||||
|
The fix:
|
||||||
|
* Optimize TileSpec to only contain a reference number that
|
||||||
|
is fast to compare, which refers to a cached string, or
|
||||||
|
* Make TextureSpec for using instead of strings
|
||||||
|
|
||||||
Configuration:
|
Configuration:
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
@ -281,18 +298,6 @@ TODO: Flowing water to actually contain flow direction information
|
|||||||
TODO: Remove duplicate lighting implementation from Map (leave
|
TODO: Remove duplicate lighting implementation from Map (leave
|
||||||
VoxelManipulator, which is faster)
|
VoxelManipulator, which is faster)
|
||||||
|
|
||||||
FIXME: The new texture stuff is slow on wine
|
|
||||||
- A basic grassy ground block takes 20-40ms
|
|
||||||
- A bit more complicated block can take 270ms
|
|
||||||
- On linux, a similar one doesn't take long at all (14ms)
|
|
||||||
- Is it a bad std::string implementation of MSVC?
|
|
||||||
- Can take up to 200ms? Is it when loading textures or always?
|
|
||||||
- Updating excess amount of meshes when making footprints is too
|
|
||||||
slow. It has to be fixed.
|
|
||||||
-> implement Map::updateNodeMeshes()
|
|
||||||
TODO: Optimize TileSpec to only contain a reference number that
|
|
||||||
is fast to compare, which refers to a cached string
|
|
||||||
|
|
||||||
Doing now:
|
Doing now:
|
||||||
----------
|
----------
|
||||||
|
|
||||||
@ -360,6 +365,7 @@ Doing now:
|
|||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "guiMainMenu.h"
|
#include "guiMainMenu.h"
|
||||||
|
#include "mineral.h"
|
||||||
|
|
||||||
IrrlichtWrapper *g_irrlicht;
|
IrrlichtWrapper *g_irrlicht;
|
||||||
|
|
||||||
@ -1445,7 +1451,6 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
// C-style stuff initialization
|
// C-style stuff initialization
|
||||||
initializeMaterialProperties();
|
initializeMaterialProperties();
|
||||||
init_mapnode();
|
|
||||||
|
|
||||||
// Debug handler
|
// Debug handler
|
||||||
BEGIN_DEBUG_EXCEPTION_HANDLER
|
BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||||
@ -1683,7 +1688,8 @@ int main(int argc, char *argv[])
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
init_content_inventory_texture_paths();
|
init_content_inventory_texture_paths();
|
||||||
//init_tile_textures();
|
init_mapnode(g_irrlicht);
|
||||||
|
init_mineral(g_irrlicht);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
GUI stuff
|
GUI stuff
|
||||||
@ -2378,7 +2384,7 @@ int main(int argc, char *argv[])
|
|||||||
bool nodefound = false;
|
bool nodefound = false;
|
||||||
v3s16 nodepos;
|
v3s16 nodepos;
|
||||||
v3s16 neighbourpos;
|
v3s16 neighbourpos;
|
||||||
core::aabbox3d<f32> nodefacebox;
|
core::aabbox3d<f32> nodehilightbox;
|
||||||
f32 mindistance = BS * 1001;
|
f32 mindistance = BS * 1001;
|
||||||
|
|
||||||
v3s16 pos_i = floatToInt(player_position);
|
v3s16 pos_i = floatToInt(player_position);
|
||||||
@ -2470,7 +2476,7 @@ int main(int argc, char *argv[])
|
|||||||
nodepos = np;
|
nodepos = np;
|
||||||
neighbourpos = np;
|
neighbourpos = np;
|
||||||
mindistance = distance;
|
mindistance = distance;
|
||||||
nodefacebox = box;
|
nodehilightbox = box;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2513,7 +2519,16 @@ int main(int argc, char *argv[])
|
|||||||
nodepos = np;
|
nodepos = np;
|
||||||
neighbourpos = np + dirs[i];
|
neighbourpos = np + dirs[i];
|
||||||
mindistance = distance;
|
mindistance = distance;
|
||||||
nodefacebox = facebox;
|
|
||||||
|
//nodehilightbox = facebox;
|
||||||
|
|
||||||
|
const float d = 0.502;
|
||||||
|
core::aabbox3d<f32> nodebox
|
||||||
|
(-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d);
|
||||||
|
v3f nodepos_f = intToFloat(nodepos);
|
||||||
|
nodebox.MinEdge += nodepos_f;
|
||||||
|
nodebox.MaxEdge += nodepos_f;
|
||||||
|
nodehilightbox = nodebox;
|
||||||
}
|
}
|
||||||
} // if distance < mindistance
|
} // if distance < mindistance
|
||||||
} // for dirs
|
} // for dirs
|
||||||
@ -2531,15 +2546,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
// Visualize selection
|
// Visualize selection
|
||||||
|
|
||||||
const float d = 0.502;
|
hilightboxes.push_back(nodehilightbox);
|
||||||
core::aabbox3d<f32> nodebox(-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d);
|
|
||||||
v3f nodepos_f = intToFloat(nodepos);
|
|
||||||
//v3f nodepos_f(nodepos.X*BS, nodepos.Y*BS, nodepos.Z*BS);
|
|
||||||
nodebox.MinEdge += nodepos_f;
|
|
||||||
nodebox.MaxEdge += nodepos_f;
|
|
||||||
hilightboxes.push_back(nodebox);
|
|
||||||
|
|
||||||
//hilightboxes.push_back(nodefacebox);
|
|
||||||
|
|
||||||
// Handle digging
|
// Handle digging
|
||||||
|
|
||||||
|
@ -263,6 +263,7 @@ void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f p,
|
|||||||
|
|
||||||
//u8 li = decode_light(light);
|
//u8 li = decode_light(light);
|
||||||
u8 li = light;
|
u8 li = light;
|
||||||
|
//u8 li = 255; //DEBUG
|
||||||
|
|
||||||
u8 alpha = tile.alpha;
|
u8 alpha = tile.alpha;
|
||||||
/*u8 alpha = 255;
|
/*u8 alpha = 255;
|
||||||
@ -309,15 +310,16 @@ TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir)
|
|||||||
struct NodeMod mod = n->getValue();
|
struct NodeMod mod = n->getValue();
|
||||||
if(mod.type == NODEMOD_CHANGECONTENT)
|
if(mod.type == NODEMOD_CHANGECONTENT)
|
||||||
{
|
{
|
||||||
//spec = content_tile(mod.param, face_dir);
|
|
||||||
MapNode mn2(mod.param);
|
MapNode mn2(mod.param);
|
||||||
spec = mn2.getTile(face_dir);
|
spec = mn2.getTile(face_dir);
|
||||||
}
|
}
|
||||||
if(mod.type == NODEMOD_CRACK)
|
if(mod.type == NODEMOD_CRACK)
|
||||||
{
|
{
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os<<"[[mod:crack"<<mod.param;
|
os<<"[crack"<<mod.param;
|
||||||
spec.name += os.str();
|
|
||||||
|
textureid_t tid = g_irrlicht->getTextureId(os.str());
|
||||||
|
spec.spec.addTid(tid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -601,7 +603,8 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
{
|
{
|
||||||
TimeTaker timer2("updateMesh() collect");
|
// 4-23ms for MAP_BLOCKSIZE=16
|
||||||
|
//TimeTaker timer2("updateMesh() collect");
|
||||||
|
|
||||||
// Lock this, as m_temp_mods will be used directly
|
// Lock this, as m_temp_mods will be used directly
|
||||||
JMutexAutoLock lock(m_temp_mods_mutex);
|
JMutexAutoLock lock(m_temp_mods_mutex);
|
||||||
@ -667,22 +670,25 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
// avg 0ms (100ms spikes when loading textures the first time)
|
// avg 0ms (100ms spikes when loading textures the first time)
|
||||||
//TimeTaker timer2("updateMesh() mesh building");
|
//TimeTaker timer2("updateMesh() mesh building");
|
||||||
|
|
||||||
|
video::SMaterial material;
|
||||||
|
material.Lighting = false;
|
||||||
|
material.BackfaceCulling = false;
|
||||||
|
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_OFF);
|
||||||
|
material.setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
|
||||||
for(u32 i=0; i<fastfaces_new.size(); i++)
|
for(u32 i=0; i<fastfaces_new.size(); i++)
|
||||||
{
|
{
|
||||||
FastFace &f = fastfaces_new[i];
|
FastFace &f = fastfaces_new[i];
|
||||||
|
|
||||||
const u16 indices[] = {0,1,2,2,3,0};
|
const u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
|
||||||
video::ITexture *texture = g_irrlicht->getTexture(f.tile.name);
|
video::ITexture *texture = g_irrlicht->getTexture(f.tile.spec);
|
||||||
video::SMaterial material;
|
|
||||||
material.Lighting = false;
|
|
||||||
material.BackfaceCulling = false;
|
|
||||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
|
||||||
material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_OFF);
|
|
||||||
material.setFlag(video::EMF_FOG_ENABLE, true);
|
|
||||||
material.setTexture(0, texture);
|
material.setTexture(0, texture);
|
||||||
if(f.tile.alpha != 255)
|
if(f.tile.alpha != 255)
|
||||||
material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
||||||
|
else
|
||||||
|
material.MaterialType = video::EMT_SOLID;
|
||||||
|
|
||||||
collector.append(material, f.vertices, 4, indices, 6);
|
collector.append(material, f.vertices, 4, indices, 6);
|
||||||
}
|
}
|
||||||
@ -691,13 +697,22 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
/*
|
/*
|
||||||
Add special graphics:
|
Add special graphics:
|
||||||
- torches
|
- torches
|
||||||
|
- flowing water
|
||||||
TODO: Optimize by using same meshbuffer for same textures
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// 0ms
|
// 0ms
|
||||||
//TimeTaker timer2("updateMesh() adding special stuff");
|
//TimeTaker timer2("updateMesh() adding special stuff");
|
||||||
|
|
||||||
|
// Flowing water material
|
||||||
|
video::SMaterial material_w1;
|
||||||
|
material_w1.setFlag(video::EMF_LIGHTING, false);
|
||||||
|
material_w1.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
material_w1.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
material_w1.setFlag(video::EMF_FOG_ENABLE, true);
|
||||||
|
material_w1.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
||||||
|
material_w1.setTexture(0,
|
||||||
|
g_irrlicht->getTexture("water.png"));
|
||||||
|
|
||||||
for(s16 z=0; z<MAP_BLOCKSIZE; z++)
|
for(s16 z=0; z<MAP_BLOCKSIZE; z++)
|
||||||
for(s16 y=0; y<MAP_BLOCKSIZE; y++)
|
for(s16 y=0; y<MAP_BLOCKSIZE; y++)
|
||||||
for(s16 x=0; x<MAP_BLOCKSIZE; x++)
|
for(s16 x=0; x<MAP_BLOCKSIZE; x++)
|
||||||
@ -751,17 +766,17 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
if(dir == v3s16(0,-1,0))
|
if(dir == v3s16(0,-1,0))
|
||||||
material.setTexture(0,
|
material.setTexture(0,
|
||||||
g_irrlicht->getTexture(porting::getDataPath("torch_on_floor.png").c_str()));
|
g_irrlicht->getTexture("torch_on_floor.png"));
|
||||||
else if(dir == v3s16(0,1,0))
|
else if(dir == v3s16(0,1,0))
|
||||||
material.setTexture(0,
|
material.setTexture(0,
|
||||||
g_irrlicht->getTexture(porting::getDataPath("torch_on_ceiling.png").c_str()));
|
g_irrlicht->getTexture("torch_on_ceiling.png"));
|
||||||
// For backwards compatibility
|
// For backwards compatibility
|
||||||
else if(dir == v3s16(0,0,0))
|
else if(dir == v3s16(0,0,0))
|
||||||
material.setTexture(0,
|
material.setTexture(0,
|
||||||
g_irrlicht->getTexture(porting::getDataPath("torch_on_floor.png").c_str()));
|
g_irrlicht->getTexture("torch_on_floor.png"));
|
||||||
else
|
else
|
||||||
material.setTexture(0,
|
material.setTexture(0,
|
||||||
g_irrlicht->getTexture(porting::getDataPath("torch.png").c_str()));
|
g_irrlicht->getTexture("torch.png"));
|
||||||
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
// Add to mesh collector
|
// Add to mesh collector
|
||||||
@ -947,19 +962,9 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
vertices[j].Pos += intToFloat(p + getPosRelative());
|
vertices[j].Pos += intToFloat(p + getPosRelative());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set material
|
|
||||||
video::SMaterial material;
|
|
||||||
material.setFlag(video::EMF_LIGHTING, false);
|
|
||||||
material.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
|
||||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
|
||||||
material.setFlag(video::EMF_FOG_ENABLE, true);
|
|
||||||
material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
|
||||||
material.setTexture(0,
|
|
||||||
g_irrlicht->getTexture(porting::getDataPath("water.png").c_str()));
|
|
||||||
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
// Add to mesh collector
|
// Add to mesh collector
|
||||||
collector.append(material, vertices, 4, indices, 6);
|
collector.append(material_w1, vertices, 4, indices, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -984,19 +989,9 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
vertices[i].Pos += intToFloat(p + getPosRelative());
|
vertices[i].Pos += intToFloat(p + getPosRelative());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set material
|
|
||||||
video::SMaterial material;
|
|
||||||
material.setFlag(video::EMF_LIGHTING, false);
|
|
||||||
material.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
|
||||||
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
|
||||||
material.setFlag(video::EMF_FOG_ENABLE, true);
|
|
||||||
material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
|
||||||
material.setTexture(0,
|
|
||||||
g_irrlicht->getTexture(porting::getDataPath("water.png").c_str()));
|
|
||||||
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
// Add to mesh collector
|
// Add to mesh collector
|
||||||
collector.append(material, vertices, 4, indices, 6);
|
collector.append(material_w1, vertices, 4, indices, 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,80 +31,85 @@ ContentFeatures::~ContentFeatures()
|
|||||||
|
|
||||||
struct ContentFeatures g_content_features[256];
|
struct ContentFeatures g_content_features[256];
|
||||||
|
|
||||||
void init_mapnode()
|
ContentFeatures & content_features(u8 i)
|
||||||
|
{
|
||||||
|
return g_content_features[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_mapnode(IrrlichtWrapper *irrlicht)
|
||||||
{
|
{
|
||||||
u8 i;
|
u8 i;
|
||||||
ContentFeatures *f = NULL;
|
ContentFeatures *f = NULL;
|
||||||
|
|
||||||
i = CONTENT_STONE;
|
i = CONTENT_STONE;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures("stone.png");
|
f->setAllTextures(irrlicht->getTextureId("stone.png"));
|
||||||
f->param_type = CPT_MINERAL;
|
f->param_type = CPT_MINERAL;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_GRASS;
|
i = CONTENT_GRASS;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
//f->setAllTextures("mud.png[[mod:sidegrass");
|
f->setAllTextures(TextureSpec(irrlicht->getTextureId("mud.png"),
|
||||||
f->setAllTextures("mud.png[[mod:blitname:grass_side.png");
|
irrlicht->getTextureId("grass_side.png")));
|
||||||
f->setTexture(0, "grass.png");
|
f->setTexture(0, irrlicht->getTextureId("grass.png"));
|
||||||
f->setTexture(1, "mud.png");
|
f->setTexture(1, irrlicht->getTextureId("mud.png"));
|
||||||
f->setInventoryImage("grass.png");
|
f->setInventoryTexture(irrlicht->getTextureId("grass.png"));
|
||||||
f->param_type = CPT_MINERAL;
|
f->param_type = CPT_MINERAL;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_GRASS_FOOTSTEPS;
|
i = CONTENT_GRASS_FOOTSTEPS;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
//f->setAllTextures("mud.png[[mod:sidegrass");
|
f->setAllTextures(TextureSpec(irrlicht->getTextureId("mud.png"),
|
||||||
f->setAllTextures("mud.png[[mod:blitname:grass_side.png");
|
irrlicht->getTextureId("grass_side.png")));
|
||||||
f->setTexture(0, "grass_footsteps.png");
|
f->setTexture(0, irrlicht->getTextureId("grass_footsteps.png"));
|
||||||
f->setTexture(1, "mud.png");
|
f->setTexture(1, irrlicht->getTextureId("mud.png"));
|
||||||
f->setInventoryImage("grass_footsteps.png");
|
f->setInventoryTexture(irrlicht->getTextureId("grass_footsteps.png"));
|
||||||
f->param_type = CPT_MINERAL;
|
f->param_type = CPT_MINERAL;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_MUD;
|
i = CONTENT_MUD;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures("mud.png");
|
f->setAllTextures(irrlicht->getTextureId("mud.png"));
|
||||||
f->param_type = CPT_MINERAL;
|
f->param_type = CPT_MINERAL;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_SAND;
|
i = CONTENT_SAND;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures("mud.png");
|
f->setAllTextures(irrlicht->getTextureId("mud.png"));
|
||||||
f->param_type = CPT_MINERAL;
|
f->param_type = CPT_MINERAL;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_TREE;
|
i = CONTENT_TREE;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures("tree.png");
|
f->setAllTextures(irrlicht->getTextureId("tree.png"));
|
||||||
f->param_type = CPT_MINERAL;
|
f->param_type = CPT_MINERAL;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_LEAVES;
|
i = CONTENT_LEAVES;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures("leaves.png");
|
f->setAllTextures(irrlicht->getTextureId("leaves.png"));
|
||||||
f->param_type = CPT_MINERAL;
|
f->param_type = CPT_MINERAL;
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_COALSTONE;
|
i = CONTENT_COALSTONE;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->translate_to = new MapNode(CONTENT_STONE, MINERAL_COAL);
|
f->translate_to = new MapNode(CONTENT_STONE, MINERAL_COAL);
|
||||||
/*f->setAllTextures("coalstone.png");
|
/*f->setAllTextures(irrlicht->getTextureId("coalstone.png"));
|
||||||
f->is_ground_content = true;*/
|
f->is_ground_content = true;*/
|
||||||
|
|
||||||
i = CONTENT_WOOD;
|
i = CONTENT_WOOD;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures("wood.png");
|
f->setAllTextures(irrlicht->getTextureId("wood.png"));
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_MESE;
|
i = CONTENT_MESE;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures("mese.png");
|
f->setAllTextures(irrlicht->getTextureId("mese.png"));
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_CLOUD;
|
i = CONTENT_CLOUD;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setAllTextures("cloud.png");
|
f->setAllTextures(irrlicht->getTextureId("cloud.png"));
|
||||||
f->is_ground_content = true;
|
f->is_ground_content = true;
|
||||||
|
|
||||||
i = CONTENT_AIR;
|
i = CONTENT_AIR;
|
||||||
@ -120,7 +125,7 @@ void init_mapnode()
|
|||||||
|
|
||||||
i = CONTENT_WATER;
|
i = CONTENT_WATER;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setInventoryImage("water.png");
|
f->setInventoryTexture(irrlicht->getTextureId("water.png"));
|
||||||
f->param_type = CPT_LIGHT;
|
f->param_type = CPT_LIGHT;
|
||||||
f->light_propagates = true;
|
f->light_propagates = true;
|
||||||
f->solidness = 0; // Drawn separately, makes no faces
|
f->solidness = 0; // Drawn separately, makes no faces
|
||||||
@ -132,8 +137,8 @@ void init_mapnode()
|
|||||||
|
|
||||||
i = CONTENT_WATERSOURCE;
|
i = CONTENT_WATERSOURCE;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setTexture(0, "water.png", WATER_ALPHA);
|
f->setTexture(0, irrlicht->getTextureId("water.png"), WATER_ALPHA);
|
||||||
f->setInventoryImage("water.png");
|
f->setInventoryTexture(irrlicht->getTextureId("water.png"));
|
||||||
f->param_type = CPT_LIGHT;
|
f->param_type = CPT_LIGHT;
|
||||||
f->light_propagates = true;
|
f->light_propagates = true;
|
||||||
f->solidness = 1;
|
f->solidness = 1;
|
||||||
@ -145,7 +150,7 @@ void init_mapnode()
|
|||||||
|
|
||||||
i = CONTENT_TORCH;
|
i = CONTENT_TORCH;
|
||||||
f = &g_content_features[i];
|
f = &g_content_features[i];
|
||||||
f->setInventoryImage("torch_on_floor.png");
|
f->setInventoryTexture(irrlicht->getTextureId("torch_on_floor.png"));
|
||||||
f->param_type = CPT_LIGHT;
|
f->param_type = CPT_LIGHT;
|
||||||
f->light_propagates = true;
|
f->light_propagates = true;
|
||||||
f->solidness = 0; // drawn separately, makes no faces
|
f->solidness = 0; // drawn separately, makes no faces
|
||||||
@ -184,12 +189,10 @@ TileSpec MapNode::getTile(v3s16 dir)
|
|||||||
if(content_features(d).param_type == CPT_MINERAL)
|
if(content_features(d).param_type == CPT_MINERAL)
|
||||||
{
|
{
|
||||||
u8 mineral = param & 0x1f;
|
u8 mineral = param & 0x1f;
|
||||||
const char *ts = mineral_block_texture(mineral);
|
// Add mineral block texture
|
||||||
if(ts[0] != 0)
|
textureid_t tid = mineral_block_texture(mineral);
|
||||||
{
|
if(tid != 0)
|
||||||
spec.name += "[[mod:blitname:";
|
spec.spec.addTid(tid);
|
||||||
spec.name += ts;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return spec;
|
return spec;
|
||||||
@ -206,14 +209,15 @@ u8 MapNode::getMineral()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pointers to c_str()s g_content_features[i].inventory_image_path
|
// Pointers to c_str()s g_content_features[i].inventory_image_path
|
||||||
const char * g_content_inventory_texture_paths[USEFUL_CONTENT_COUNT] = {0};
|
//const char * g_content_inventory_texture_paths[USEFUL_CONTENT_COUNT] = {0};
|
||||||
|
|
||||||
void init_content_inventory_texture_paths()
|
void init_content_inventory_texture_paths()
|
||||||
{
|
{
|
||||||
for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
|
dstream<<"DEPRECATED "<<__FUNCTION_NAME<<std::endl;
|
||||||
|
/*for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
|
||||||
{
|
{
|
||||||
g_content_inventory_texture_paths[i] =
|
g_content_inventory_texture_paths[i] =
|
||||||
g_content_features[i].inventory_image_path.c_str();
|
g_content_features[i].inventory_image_path.c_str();
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,11 +27,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "serialization.h"
|
#include "serialization.h"
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
|
#include "irrlichtwrapper.h"
|
||||||
|
|
||||||
// Initializes all kind of stuff in here.
|
/*
|
||||||
// Doesn't depend on anything else.
|
Initializes all kind of stuff in here.
|
||||||
// Many things depend on this.
|
Many things depend on this.
|
||||||
void init_mapnode();
|
|
||||||
|
irrlicht: Used for getting texture ids.
|
||||||
|
*/
|
||||||
|
void init_mapnode(IrrlichtWrapper *irrlicht);
|
||||||
|
|
||||||
// Initializes g_content_inventory_texture_paths
|
// Initializes g_content_inventory_texture_paths
|
||||||
void init_content_inventory_texture_paths();
|
void init_content_inventory_texture_paths();
|
||||||
@ -129,7 +133,8 @@ struct ContentFeatures
|
|||||||
*/
|
*/
|
||||||
TileSpec tiles[6];
|
TileSpec tiles[6];
|
||||||
|
|
||||||
std::string inventory_image_path;
|
//std::string inventory_image_path;
|
||||||
|
TextureSpec inventory_texture;
|
||||||
|
|
||||||
bool is_ground_content; //TODO: Remove, use walkable instead
|
bool is_ground_content; //TODO: Remove, use walkable instead
|
||||||
bool light_propagates;
|
bool light_propagates;
|
||||||
@ -162,39 +167,42 @@ struct ContentFeatures
|
|||||||
|
|
||||||
~ContentFeatures();
|
~ContentFeatures();
|
||||||
|
|
||||||
void setAllTextures(std::string imgname, u8 alpha=255)
|
void setAllTextures(const TextureSpec &spec, u8 alpha=255)
|
||||||
{
|
{
|
||||||
for(u16 i=0; i<6; i++)
|
for(u16 i=0; i<6; i++)
|
||||||
{
|
{
|
||||||
tiles[i].name = porting::getDataPath(imgname.c_str());
|
tiles[i].spec = spec;
|
||||||
tiles[i].alpha = alpha;
|
tiles[i].alpha = alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set this too so it can be left as is most times
|
// Set this too so it can be left as is most times
|
||||||
if(inventory_image_path == "")
|
/*if(inventory_image_path == "")
|
||||||
inventory_image_path = porting::getDataPath(imgname.c_str());
|
inventory_image_path = porting::getDataPath(imgname.c_str());*/
|
||||||
|
|
||||||
|
if(inventory_texture.empty())
|
||||||
|
inventory_texture = spec;
|
||||||
}
|
}
|
||||||
void setTexture(u16 i, std::string imgname, u8 alpha=255)
|
void setTexture(u16 i, const TextureSpec &spec, u8 alpha=255)
|
||||||
{
|
{
|
||||||
tiles[i].name = porting::getDataPath(imgname.c_str());
|
tiles[i].spec = spec;
|
||||||
tiles[i].alpha = alpha;
|
tiles[i].alpha = alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setInventoryImage(std::string imgname)
|
void setInventoryTexture(const TextureSpec &spec)
|
||||||
|
{
|
||||||
|
inventory_texture = spec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*void setInventoryImage(std::string imgname)
|
||||||
{
|
{
|
||||||
inventory_image_path = porting::getDataPath(imgname.c_str());
|
inventory_image_path = porting::getDataPath(imgname.c_str());
|
||||||
}
|
}*/
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialized by init_mapnode()
|
/*
|
||||||
extern struct ContentFeatures g_content_features[256];
|
Call this to access the ContentFeature list
|
||||||
|
*/
|
||||||
inline ContentFeatures & content_features(u8 i)
|
ContentFeatures & content_features(u8 i);
|
||||||
{
|
|
||||||
return g_content_features[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const char * g_content_inventory_texture_paths[USEFUL_CONTENT_COUNT];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If true, the material allows light propagation and brightness is stored
|
If true, the material allows light propagation and brightness is stored
|
||||||
@ -203,7 +211,7 @@ extern const char * g_content_inventory_texture_paths[USEFUL_CONTENT_COUNT];
|
|||||||
*/
|
*/
|
||||||
inline bool light_propagates_content(u8 m)
|
inline bool light_propagates_content(u8 m)
|
||||||
{
|
{
|
||||||
return g_content_features[m].light_propagates;
|
return content_features(m).light_propagates;
|
||||||
//return (m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
|
//return (m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,7 +222,7 @@ inline bool light_propagates_content(u8 m)
|
|||||||
*/
|
*/
|
||||||
inline bool sunlight_propagates_content(u8 m)
|
inline bool sunlight_propagates_content(u8 m)
|
||||||
{
|
{
|
||||||
return g_content_features[m].sunlight_propagates;
|
return content_features(m).sunlight_propagates;
|
||||||
//return (m == CONTENT_AIR || m == CONTENT_TORCH);
|
//return (m == CONTENT_AIR || m == CONTENT_TORCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +236,7 @@ inline bool sunlight_propagates_content(u8 m)
|
|||||||
*/
|
*/
|
||||||
inline u8 content_solidness(u8 m)
|
inline u8 content_solidness(u8 m)
|
||||||
{
|
{
|
||||||
return g_content_features[m].solidness;
|
return content_features(m).solidness;
|
||||||
/*// As of now, every pseudo node like torches are added to this
|
/*// As of now, every pseudo node like torches are added to this
|
||||||
if(m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER)
|
if(m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER)
|
||||||
return 0;
|
return 0;
|
||||||
@ -241,28 +249,28 @@ inline u8 content_solidness(u8 m)
|
|||||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||||
inline bool content_walkable(u8 m)
|
inline bool content_walkable(u8 m)
|
||||||
{
|
{
|
||||||
return g_content_features[m].walkable;
|
return content_features(m).walkable;
|
||||||
//return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE && m != CONTENT_TORCH);
|
//return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE && m != CONTENT_TORCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||||
inline bool content_liquid(u8 m)
|
inline bool content_liquid(u8 m)
|
||||||
{
|
{
|
||||||
return g_content_features[m].liquid_type != LIQUID_NONE;
|
return content_features(m).liquid_type != LIQUID_NONE;
|
||||||
//return (m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
|
//return (m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||||
inline bool content_flowing_liquid(u8 m)
|
inline bool content_flowing_liquid(u8 m)
|
||||||
{
|
{
|
||||||
return g_content_features[m].liquid_type == LIQUID_FLOWING;
|
return content_features(m).liquid_type == LIQUID_FLOWING;
|
||||||
//return (m == CONTENT_WATER);
|
//return (m == CONTENT_WATER);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||||
inline bool content_liquid_source(u8 m)
|
inline bool content_liquid_source(u8 m)
|
||||||
{
|
{
|
||||||
return g_content_features[m].liquid_type == LIQUID_SOURCE;
|
return content_features(m).liquid_type == LIQUID_SOURCE;
|
||||||
//return (m == CONTENT_WATERSOURCE);
|
//return (m == CONTENT_WATERSOURCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,21 +287,21 @@ inline u8 make_liquid_flowing(u8 m)
|
|||||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||||
inline bool content_pointable(u8 m)
|
inline bool content_pointable(u8 m)
|
||||||
{
|
{
|
||||||
return g_content_features[m].pointable;
|
return content_features(m).pointable;
|
||||||
//return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE);
|
//return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||||
inline bool content_diggable(u8 m)
|
inline bool content_diggable(u8 m)
|
||||||
{
|
{
|
||||||
return g_content_features[m].diggable;
|
return content_features(m).diggable;
|
||||||
//return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE);
|
//return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||||
inline bool content_buildable_to(u8 m)
|
inline bool content_buildable_to(u8 m)
|
||||||
{
|
{
|
||||||
return g_content_features[m].buildable_to;
|
return content_features(m).buildable_to;
|
||||||
//return (m == CONTENT_AIR || m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
|
//return (m == CONTENT_AIR || m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +311,7 @@ inline bool content_buildable_to(u8 m)
|
|||||||
*/
|
*/
|
||||||
/*inline bool is_ground_content(u8 m)
|
/*inline bool is_ground_content(u8 m)
|
||||||
{
|
{
|
||||||
return g_content_features[m].is_ground_content;
|
return content_features(m).is_ground_content;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -622,7 +630,7 @@ struct MapNode
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Translate deprecated stuff
|
// Translate deprecated stuff
|
||||||
MapNode *translate_to = g_content_features[d].translate_to;
|
MapNode *translate_to = content_features(d).translate_to;
|
||||||
if(translate_to)
|
if(translate_to)
|
||||||
{
|
{
|
||||||
dstream<<"MapNode: WARNING: Translating "<<d<<" to "
|
dstream<<"MapNode: WARNING: Translating "<<d<<" to "
|
||||||
|
49
src/mineral.cpp
Normal file
49
src/mineral.cpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mineral.h"
|
||||||
|
|
||||||
|
const char *mineral_filenames[MINERAL_COUNT] =
|
||||||
|
{
|
||||||
|
NULL,
|
||||||
|
"mineral_coal.png",
|
||||||
|
"mineral_iron.png"
|
||||||
|
};
|
||||||
|
|
||||||
|
textureid_t mineral_textures[MINERAL_COUNT] = {0};
|
||||||
|
|
||||||
|
void init_mineral(IrrlichtWrapper *irrlicht)
|
||||||
|
{
|
||||||
|
for(u32 i=0; i<MINERAL_COUNT; i++)
|
||||||
|
{
|
||||||
|
if(mineral_filenames[i] == NULL)
|
||||||
|
continue;
|
||||||
|
mineral_textures[i] = irrlicht->getTextureId(mineral_filenames[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
textureid_t mineral_block_texture(u8 mineral)
|
||||||
|
{
|
||||||
|
if(mineral >= MINERAL_COUNT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return mineral_textures[mineral];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -21,6 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#define MINERAL_HEADER
|
#define MINERAL_HEADER
|
||||||
|
|
||||||
#include "inventory.h"
|
#include "inventory.h"
|
||||||
|
#include "texture.h"
|
||||||
|
#include "irrlichtwrapper.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Minerals
|
Minerals
|
||||||
@ -29,22 +31,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
type param.
|
type param.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Caches textures
|
||||||
|
void init_mineral(IrrlichtWrapper *irrlicht);
|
||||||
|
|
||||||
#define MINERAL_NONE 0
|
#define MINERAL_NONE 0
|
||||||
#define MINERAL_COAL 1
|
#define MINERAL_COAL 1
|
||||||
#define MINERAL_IRON 2
|
#define MINERAL_IRON 2
|
||||||
|
|
||||||
inline const char * mineral_block_texture(u8 mineral)
|
#define MINERAL_COUNT 3
|
||||||
{
|
|
||||||
switch(mineral)
|
textureid_t mineral_block_texture(u8 mineral);
|
||||||
{
|
|
||||||
case MINERAL_COAL:
|
|
||||||
return "mineral_coal.png";
|
|
||||||
case MINERAL_IRON:
|
|
||||||
return "mineral_iron.png";
|
|
||||||
default:
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline CraftItem * getDiggedMineralItem(u8 mineral)
|
inline CraftItem * getDiggedMineralItem(u8 mineral)
|
||||||
{
|
{
|
||||||
|
@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
#include "utility.h"
|
||||||
|
|
||||||
Player::Player():
|
Player::Player():
|
||||||
touching_ground(false),
|
touching_ground(false),
|
||||||
@ -34,15 +35,21 @@ Player::Player():
|
|||||||
m_position(0,0,0)
|
m_position(0,0,0)
|
||||||
{
|
{
|
||||||
updateName("<not set>");
|
updateName("<not set>");
|
||||||
inventory.addList("main", PLAYER_INVENTORY_SIZE);
|
resetInventory();
|
||||||
inventory.addList("craft", 9);
|
|
||||||
inventory.addList("craftresult", 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Player::~Player()
|
Player::~Player()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::resetInventory()
|
||||||
|
{
|
||||||
|
inventory.clear();
|
||||||
|
inventory.addList("main", PLAYER_INVENTORY_SIZE);
|
||||||
|
inventory.addList("craft", 9);
|
||||||
|
inventory.addList("craftresult", 1);
|
||||||
|
}
|
||||||
|
|
||||||
// Y direction is ignored
|
// Y direction is ignored
|
||||||
void Player::accelerate(v3f target_speed, f32 max_increase)
|
void Player::accelerate(v3f target_speed, f32 max_increase)
|
||||||
{
|
{
|
||||||
@ -80,6 +87,50 @@ void Player::accelerate(v3f target_speed, f32 max_increase)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::serialize(std::ostream &os)
|
||||||
|
{
|
||||||
|
// Utilize a Settings object for storing values
|
||||||
|
Settings args;
|
||||||
|
args.setS32("version", 1);
|
||||||
|
args.set("name", m_name);
|
||||||
|
args.setFloat("pitch", m_pitch);
|
||||||
|
args.setFloat("yaw", m_yaw);
|
||||||
|
args.setV3F("position", m_position);
|
||||||
|
|
||||||
|
args.writeLines(os);
|
||||||
|
|
||||||
|
os<<"PlayerArgsEnd\n";
|
||||||
|
|
||||||
|
inventory.serialize(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::deSerialize(std::istream &is)
|
||||||
|
{
|
||||||
|
Settings args;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if(is.eof())
|
||||||
|
throw SerializationError
|
||||||
|
("Player::deSerialize(): PlayerArgsEnd not found");
|
||||||
|
std::string line;
|
||||||
|
std::getline(is, line);
|
||||||
|
std::string trimmedline = trim(line);
|
||||||
|
if(trimmedline == "PlayerArgsEnd")
|
||||||
|
break;
|
||||||
|
args.parseConfigLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
//args.getS32("version");
|
||||||
|
std::string name = args.get("name");
|
||||||
|
updateName(name.c_str());
|
||||||
|
m_pitch = args.getFloat("pitch");
|
||||||
|
m_yaw = args.getFloat("yaw");
|
||||||
|
m_position = args.getV3F("position");
|
||||||
|
|
||||||
|
inventory.deSerialize(is);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
RemotePlayer
|
RemotePlayer
|
||||||
*/
|
*/
|
||||||
|
28
src/player.h
28
src/player.h
@ -29,6 +29,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#define PLAYERNAME_SIZE 20
|
#define PLAYERNAME_SIZE 20
|
||||||
|
|
||||||
|
#define PLAYERNAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.,"
|
||||||
|
|
||||||
class Map;
|
class Map;
|
||||||
|
|
||||||
class Player
|
class Player
|
||||||
@ -37,6 +39,8 @@ public:
|
|||||||
Player();
|
Player();
|
||||||
virtual ~Player();
|
virtual ~Player();
|
||||||
|
|
||||||
|
void resetInventory();
|
||||||
|
|
||||||
//void move(f32 dtime, Map &map);
|
//void move(f32 dtime, Map &map);
|
||||||
virtual void move(f32 dtime, Map &map) = 0;
|
virtual void move(f32 dtime, Map &map) = 0;
|
||||||
|
|
||||||
@ -100,6 +104,14 @@ public:
|
|||||||
// NOTE: Use peer_id == 0 for disconnected
|
// NOTE: Use peer_id == 0 for disconnected
|
||||||
/*virtual bool isClientConnected() { return false; }
|
/*virtual bool isClientConnected() { return false; }
|
||||||
virtual void setClientConnected(bool) {}*/
|
virtual void setClientConnected(bool) {}*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
serialize() writes a bunch of text that can contain
|
||||||
|
any characters except a '\0', and such an ending that
|
||||||
|
deSerialize stops reading exactly at the right point.
|
||||||
|
*/
|
||||||
|
void serialize(std::ostream &os);
|
||||||
|
void deSerialize(std::istream &is);
|
||||||
|
|
||||||
bool touching_ground;
|
bool touching_ground;
|
||||||
bool in_water;
|
bool in_water;
|
||||||
@ -119,8 +131,6 @@ protected:
|
|||||||
class ServerRemotePlayer : public Player
|
class ServerRemotePlayer : public Player
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*ServerRemotePlayer(bool client_connected):
|
|
||||||
m_client_connected(client_connected)*/
|
|
||||||
ServerRemotePlayer()
|
ServerRemotePlayer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -137,18 +147,6 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/*virtual bool isClientConnected()
|
|
||||||
{
|
|
||||||
return m_client_connected;
|
|
||||||
}
|
|
||||||
virtual void setClientConnected(bool client_connected)
|
|
||||||
{
|
|
||||||
m_client_connected = client_connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This
|
|
||||||
bool m_client_connected;*/
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -252,7 +250,7 @@ private:
|
|||||||
v3f m_showpos;
|
v3f m_showpos;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // !SERVER
|
||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
struct PlayerControl
|
struct PlayerControl
|
||||||
|
194
src/server.cpp
194
src/server.cpp
@ -1000,7 +1000,8 @@ Server::Server(
|
|||||||
m_time_of_day(9000),
|
m_time_of_day(9000),
|
||||||
m_time_counter(0),
|
m_time_counter(0),
|
||||||
m_time_of_day_send_timer(0),
|
m_time_of_day_send_timer(0),
|
||||||
m_uptime(0)
|
m_uptime(0),
|
||||||
|
m_mapsavedir(mapsavedir)
|
||||||
{
|
{
|
||||||
//m_flowwater_timer = 0.0;
|
//m_flowwater_timer = 0.0;
|
||||||
m_liquid_transform_timer = 0.0;
|
m_liquid_transform_timer = 0.0;
|
||||||
@ -1013,10 +1014,16 @@ Server::Server(
|
|||||||
m_con_mutex.Init();
|
m_con_mutex.Init();
|
||||||
m_step_dtime_mutex.Init();
|
m_step_dtime_mutex.Init();
|
||||||
m_step_dtime = 0.0;
|
m_step_dtime = 0.0;
|
||||||
|
|
||||||
|
// Load players
|
||||||
|
m_env.deSerializePlayers(m_mapsavedir);
|
||||||
}
|
}
|
||||||
|
|
||||||
Server::~Server()
|
Server::~Server()
|
||||||
{
|
{
|
||||||
|
// Save players
|
||||||
|
m_env.serializePlayers(m_mapsavedir);
|
||||||
|
|
||||||
// Stop threads
|
// Stop threads
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
@ -1222,82 +1229,6 @@ void Server::AsyncRunStep()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
Update water
|
|
||||||
*/
|
|
||||||
if(g_settings.getBool("water_moves") == true)
|
|
||||||
{
|
|
||||||
float interval;
|
|
||||||
|
|
||||||
if(g_settings.getBool("endless_water") == false)
|
|
||||||
interval = 1.0;
|
|
||||||
else
|
|
||||||
interval = 0.25;
|
|
||||||
|
|
||||||
float &counter = m_flowwater_timer;
|
|
||||||
counter += dtime;
|
|
||||||
if(counter >= 0.25 && m_flow_active_nodes.size() > 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
counter = 0.0;
|
|
||||||
|
|
||||||
core::map<v3s16, MapBlock*> modified_blocks;
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
JMutexAutoLock envlock(m_env_mutex);
|
|
||||||
|
|
||||||
MapVoxelManipulator v(&m_env.getMap());
|
|
||||||
v.m_disable_water_climb =
|
|
||||||
g_settings.getBool("disable_water_climb");
|
|
||||||
|
|
||||||
if(g_settings.getBool("endless_water") == false)
|
|
||||||
v.flowWater(m_flow_active_nodes, 0, false, 250);
|
|
||||||
else
|
|
||||||
v.flowWater(m_flow_active_nodes, 0, false, 50);
|
|
||||||
|
|
||||||
v.blitBack(modified_blocks);
|
|
||||||
|
|
||||||
ServerMap &map = ((ServerMap&)m_env.getMap());
|
|
||||||
|
|
||||||
// Update lighting
|
|
||||||
core::map<v3s16, MapBlock*> lighting_modified_blocks;
|
|
||||||
map.updateLighting(modified_blocks, lighting_modified_blocks);
|
|
||||||
|
|
||||||
// Add blocks modified by lighting to modified_blocks
|
|
||||||
for(core::map<v3s16, MapBlock*>::Iterator
|
|
||||||
i = lighting_modified_blocks.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
MapBlock *block = i.getNode()->getValue();
|
|
||||||
modified_blocks.insert(block->getPos(), block);
|
|
||||||
}
|
|
||||||
} // envlock
|
|
||||||
|
|
||||||
/*
|
|
||||||
Set the modified blocks unsent for all the clients
|
|
||||||
*/
|
|
||||||
|
|
||||||
JMutexAutoLock lock2(m_con_mutex);
|
|
||||||
|
|
||||||
for(core::map<u16, RemoteClient*>::Iterator
|
|
||||||
i = m_clients.getIterator();
|
|
||||||
i.atEnd() == false; i++)
|
|
||||||
{
|
|
||||||
RemoteClient *client = i.getNode()->getValue();
|
|
||||||
|
|
||||||
if(modified_blocks.size() > 0)
|
|
||||||
{
|
|
||||||
// Remove block from sent history
|
|
||||||
client->SetBlocksNotSent(modified_blocks);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // interval counter
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Periodically print some info
|
// Periodically print some info
|
||||||
{
|
{
|
||||||
float &counter = m_print_info_timer;
|
float &counter = m_print_info_timer;
|
||||||
@ -1476,6 +1407,9 @@ void Server::AsyncRunStep()
|
|||||||
dout_server<<"Server: Unloaded "<<deleted_count
|
dout_server<<"Server: Unloaded "<<deleted_count
|
||||||
<<" sectors from memory"<<std::endl;
|
<<" sectors from memory"<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save players
|
||||||
|
m_env.serializePlayers(m_mapsavedir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1601,6 +1535,16 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||||||
Player *player = emergePlayer(playername, "", peer_id);
|
Player *player = emergePlayer(playername, "", peer_id);
|
||||||
//Player *player = m_env.getPlayer(peer_id);
|
//Player *player = m_env.getPlayer(peer_id);
|
||||||
|
|
||||||
|
/*{
|
||||||
|
// DEBUG: Test serialization
|
||||||
|
std::ostringstream test_os;
|
||||||
|
player->serialize(test_os);
|
||||||
|
dstream<<"Player serialization test: \""<<test_os.str()
|
||||||
|
<<"\""<<std::endl;
|
||||||
|
std::istringstream test_is(test_os.str());
|
||||||
|
player->deSerialize(test_is);
|
||||||
|
}*/
|
||||||
|
|
||||||
// If failed, cancel
|
// If failed, cancel
|
||||||
if(player == NULL)
|
if(player == NULL)
|
||||||
{
|
{
|
||||||
@ -2950,7 +2894,7 @@ void Server::SendInventory(u16 peer_id)
|
|||||||
if(!found)
|
if(!found)
|
||||||
{
|
{
|
||||||
ItemSpec specs[9];
|
ItemSpec specs[9];
|
||||||
specs[0] = ItemSpec(ITEM_CRAFT, "Coal");
|
specs[0] = ItemSpec(ITEM_CRAFT, "lump_of_coal");
|
||||||
specs[3] = ItemSpec(ITEM_CRAFT, "Stick");
|
specs[3] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
if(checkItemCombination(items, specs))
|
if(checkItemCombination(items, specs))
|
||||||
{
|
{
|
||||||
@ -3147,6 +3091,50 @@ RemoteClient* Server::getClient(u16 peer_id)
|
|||||||
return n->getValue();
|
return n->getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setCreativeInventory(Player *player)
|
||||||
|
{
|
||||||
|
player->resetInventory();
|
||||||
|
|
||||||
|
// Give some good picks
|
||||||
|
{
|
||||||
|
InventoryItem *item = new ToolItem("STPick", 0);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InventoryItem *item = new ToolItem("MesePick", 0);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Give materials
|
||||||
|
*/
|
||||||
|
assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE);
|
||||||
|
|
||||||
|
// add torch first
|
||||||
|
InventoryItem *item = new MaterialItem(CONTENT_TORCH, 1);
|
||||||
|
player->inventory.addItem("main", item);
|
||||||
|
|
||||||
|
// Then others
|
||||||
|
for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
|
||||||
|
{
|
||||||
|
// Skip some materials
|
||||||
|
if(i == CONTENT_WATER || i == CONTENT_TORCH
|
||||||
|
|| i == CONTENT_COALSTONE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
InventoryItem *item = new MaterialItem(i, 1);
|
||||||
|
player->inventory.addItem("main", item);
|
||||||
|
}
|
||||||
|
// Sign
|
||||||
|
{
|
||||||
|
InventoryItem *item = new MapBlockObjectItem("Sign Example text");
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Player *Server::emergePlayer(const char *name, const char *password,
|
Player *Server::emergePlayer(const char *name, const char *password,
|
||||||
u16 peer_id)
|
u16 peer_id)
|
||||||
{
|
{
|
||||||
@ -3162,8 +3150,16 @@ Player *Server::emergePlayer(const char *name, const char *password,
|
|||||||
dstream<<"emergePlayer(): Player already connected"<<std::endl;
|
dstream<<"emergePlayer(): Player already connected"<<std::endl;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Got one.
|
// Got one.
|
||||||
player->peer_id = peer_id;
|
player->peer_id = peer_id;
|
||||||
|
|
||||||
|
// Reset inventory to creative if in creative mode
|
||||||
|
if(g_settings.getBool("creative_mode"))
|
||||||
|
{
|
||||||
|
setCreativeInventory(player);
|
||||||
|
}
|
||||||
|
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3271,51 +3267,15 @@ Player *Server::emergePlayer(const char *name, const char *password,
|
|||||||
|
|
||||||
if(g_settings.getBool("creative_mode"))
|
if(g_settings.getBool("creative_mode"))
|
||||||
{
|
{
|
||||||
// Give some good picks
|
setCreativeInventory(player);
|
||||||
{
|
|
||||||
InventoryItem *item = new ToolItem("STPick", 0);
|
|
||||||
void* r = player->inventory.addItem("main", item);
|
|
||||||
assert(r == NULL);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
InventoryItem *item = new ToolItem("MesePick", 0);
|
|
||||||
void* r = player->inventory.addItem("main", item);
|
|
||||||
assert(r == NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Give materials
|
|
||||||
*/
|
|
||||||
assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE);
|
|
||||||
|
|
||||||
// add torch first
|
|
||||||
InventoryItem *item = new MaterialItem(CONTENT_TORCH, 1);
|
|
||||||
player->inventory.addItem("main", item);
|
|
||||||
|
|
||||||
// Then others
|
|
||||||
for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
|
|
||||||
{
|
|
||||||
// Skip some materials
|
|
||||||
if(i == CONTENT_WATER || i == CONTENT_TORCH)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
InventoryItem *item = new MaterialItem(i, 1);
|
|
||||||
player->inventory.addItem("main", item);
|
|
||||||
}
|
|
||||||
// Sign
|
|
||||||
{
|
|
||||||
InventoryItem *item = new MapBlockObjectItem("Sign Example text");
|
|
||||||
void* r = player->inventory.addItem("main", item);
|
|
||||||
assert(r == NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
{
|
/*{
|
||||||
InventoryItem *item = new ToolItem("WPick", 32000);
|
InventoryItem *item = new ToolItem("WPick", 32000);
|
||||||
void* r = player->inventory.addItem("main", item);
|
void* r = player->inventory.addItem("main", item);
|
||||||
assert(r == NULL);
|
assert(r == NULL);
|
||||||
}
|
}*/
|
||||||
/*{
|
/*{
|
||||||
InventoryItem *item = new MaterialItem(CONTENT_MESE, 6);
|
InventoryItem *item = new MaterialItem(CONTENT_MESE, 6);
|
||||||
void* r = player->inventory.addItem("main", item);
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
@ -508,6 +508,8 @@ private:
|
|||||||
|
|
||||||
Queue<PeerChange> m_peer_change_queue;
|
Queue<PeerChange> m_peer_change_queue;
|
||||||
|
|
||||||
|
std::string m_mapsavedir;
|
||||||
|
|
||||||
friend class EmergeThread;
|
friend class EmergeThread;
|
||||||
friend class RemoteClient;
|
friend class RemoteClient;
|
||||||
};
|
};
|
||||||
|
124
src/texture.h
Normal file
124
src/texture.h
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TEXTURE_HEADER
|
||||||
|
#define TEXTURE_HEADER
|
||||||
|
|
||||||
|
#include "common_irrlicht.h"
|
||||||
|
//#include "utility.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
All textures are given a "texture id".
|
||||||
|
0 = nothing (a NULL pointer texture)
|
||||||
|
*/
|
||||||
|
typedef u16 textureid_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Every texture in the game can be specified by this.
|
||||||
|
|
||||||
|
It exists instead of specification strings because arbitary
|
||||||
|
texture combinations for map nodes are handled using this,
|
||||||
|
and strings are too slow for that purpose.
|
||||||
|
|
||||||
|
Plain texture pointers are not used because they don't contain
|
||||||
|
content information by themselves. A texture can be completely
|
||||||
|
reconstructed by just looking at this, while this also is a
|
||||||
|
fast unique key to containers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TEXTURE_SPEC_TEXTURE_COUNT 4
|
||||||
|
|
||||||
|
struct TextureSpec
|
||||||
|
{
|
||||||
|
TextureSpec()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureSpec(textureid_t id0)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
tids[0] = id0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureSpec(textureid_t id0, textureid_t id1)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
tids[0] = id0;
|
||||||
|
tids[1] = id1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
for(u32 i=0; i<TEXTURE_SPEC_TEXTURE_COUNT; i++)
|
||||||
|
{
|
||||||
|
tids[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
for(u32 i=0; i<TEXTURE_SPEC_TEXTURE_COUNT; i++)
|
||||||
|
{
|
||||||
|
if(tids[i] != 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addTid(textureid_t tid)
|
||||||
|
{
|
||||||
|
for(u32 i=0; i<TEXTURE_SPEC_TEXTURE_COUNT; i++)
|
||||||
|
{
|
||||||
|
if(tids[i] == 0)
|
||||||
|
{
|
||||||
|
tids[i] = tid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Too many textures
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const TextureSpec &other) const
|
||||||
|
{
|
||||||
|
for(u32 i=0; i<TEXTURE_SPEC_TEXTURE_COUNT; i++)
|
||||||
|
{
|
||||||
|
if(tids[i] != other.tids[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const TextureSpec &other) const
|
||||||
|
{
|
||||||
|
for(u32 i=0; i<TEXTURE_SPEC_TEXTURE_COUNT; i++)
|
||||||
|
{
|
||||||
|
if(tids[i] >= other.tids[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ids of textures. They are blit on each other.
|
||||||
|
textureid_t tids[TEXTURE_SPEC_TEXTURE_COUNT];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
19
src/tile.h
19
src/tile.h
@ -22,8 +22,26 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
//#include "utility.h"
|
//#include "utility.h"
|
||||||
|
#include "texture.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
struct TileSpec
|
||||||
|
{
|
||||||
|
TileSpec():
|
||||||
|
alpha(255)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(TileSpec &other)
|
||||||
|
{
|
||||||
|
return (spec == other.spec && alpha == other.alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureSpec spec;
|
||||||
|
u8 alpha;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
struct TileSpec
|
struct TileSpec
|
||||||
{
|
{
|
||||||
TileSpec():
|
TileSpec():
|
||||||
@ -52,5 +70,6 @@ struct TileSpec
|
|||||||
std::string name;
|
std::string name;
|
||||||
u8 alpha;
|
u8 alpha;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
187
src/utility.h
187
src/utility.h
@ -760,17 +760,20 @@ class Settings
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Returns false on EOF
|
void writeLines(std::ostream &os)
|
||||||
bool parseConfigObject(std::istream &is)
|
|
||||||
{
|
{
|
||||||
if(is.eof())
|
for(core::map<std::string, std::string>::Iterator
|
||||||
return false;
|
i = m_settings.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
// NOTE: This function will be expanded to allow multi-line settings
|
{
|
||||||
std::string line;
|
std::string name = i.getNode()->getKey();
|
||||||
std::getline(is, line);
|
std::string value = i.getNode()->getValue();
|
||||||
//dstream<<"got line: \""<<line<<"\""<<std::endl;
|
os<<name<<" = "<<value<<"\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parseConfigLine(const std::string &line)
|
||||||
|
{
|
||||||
std::string trimmedline = trim(line);
|
std::string trimmedline = trim(line);
|
||||||
|
|
||||||
// Ignore comments
|
// Ignore comments
|
||||||
@ -798,6 +801,23 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns false on EOF
|
||||||
|
bool parseConfigObject(std::istream &is)
|
||||||
|
{
|
||||||
|
if(is.eof())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOTE: This function might be expanded to allow multi-line
|
||||||
|
settings.
|
||||||
|
*/
|
||||||
|
std::string line;
|
||||||
|
std::getline(is, line);
|
||||||
|
//dstream<<"got line: \""<<line<<"\""<<std::endl;
|
||||||
|
|
||||||
|
return parseConfigLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Read configuration file
|
Read configuration file
|
||||||
|
|
||||||
@ -1089,10 +1109,7 @@ public:
|
|||||||
|
|
||||||
float getFloat(std::string name)
|
float getFloat(std::string name)
|
||||||
{
|
{
|
||||||
float f;
|
return stof(get(name));
|
||||||
std::istringstream vis(get(name));
|
|
||||||
vis>>f;
|
|
||||||
return f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 getU16(std::string name)
|
u16 getU16(std::string name)
|
||||||
@ -1128,6 +1145,34 @@ public:
|
|||||||
return stoi(get(name));
|
return stoi(get(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v3f getV3F(std::string name)
|
||||||
|
{
|
||||||
|
v3f value;
|
||||||
|
Strfnd f(get(name));
|
||||||
|
f.next("(");
|
||||||
|
value.X = stof(f.next(","));
|
||||||
|
value.Y = stof(f.next(","));
|
||||||
|
value.Z = stof(f.next(")"));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setS32(std::string name, s32 value)
|
||||||
|
{
|
||||||
|
set(name, itos(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFloat(std::string name, float value)
|
||||||
|
{
|
||||||
|
set(name, ftos(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setV3F(std::string name, v3f value)
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
os<<"("<<value.X<<","<<value.Y<<","<<value.Z<<")";
|
||||||
|
set(name, os.str());
|
||||||
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
m_settings.clear();
|
m_settings.clear();
|
||||||
@ -1628,5 +1673,121 @@ private:
|
|||||||
core::list<Value> m_list;
|
core::list<Value> m_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
template<typename Key, typename Value>
|
||||||
|
class MutexedCache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MutexedCache()
|
||||||
|
{
|
||||||
|
m_mutex.Init();
|
||||||
|
assert(m_mutex.IsInitialized());
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(const Key &name, const Value &value)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
m_values[name] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get(const Key &name, Value *result)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
|
typename core::map<Key, Value>::Node *n;
|
||||||
|
n = m_values.find(name);
|
||||||
|
|
||||||
|
if(n == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*result = n->getValue();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
core::map<Key, Value> m_values;
|
||||||
|
JMutex m_mutex;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
Generates ids for comparable values.
|
||||||
|
Id=0 is reserved for "no value".
|
||||||
|
|
||||||
|
Is fast at:
|
||||||
|
- Returning value by id (very fast)
|
||||||
|
- Returning id by value
|
||||||
|
- Generating a new id for a value
|
||||||
|
|
||||||
|
Is not able to:
|
||||||
|
- Remove an id/value pair (is possible to implement but slow)
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
class MutexedIdGenerator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MutexedIdGenerator()
|
||||||
|
{
|
||||||
|
m_mutex.Init();
|
||||||
|
assert(m_mutex.IsInitialized());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if found
|
||||||
|
bool getValue(u32 id, T &value)
|
||||||
|
{
|
||||||
|
if(id == 0)
|
||||||
|
return false;
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
if(m_id_to_value.size() < id)
|
||||||
|
return false;
|
||||||
|
value = m_id_to_value[id-1];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If id exists for value, returns the id.
|
||||||
|
// Otherwise generates an id for the value.
|
||||||
|
u32 getId(const T &value)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
typename core::map<T, u32>::Node *n;
|
||||||
|
n = m_value_to_id.find(value);
|
||||||
|
if(n != NULL)
|
||||||
|
return n->getValue();
|
||||||
|
m_id_to_value.push_back(value);
|
||||||
|
u32 new_id = m_id_to_value.size();
|
||||||
|
m_value_to_id.insert(value, new_id);
|
||||||
|
return new_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
JMutex m_mutex;
|
||||||
|
// Values are stored here at id-1 position (id 1 = [0])
|
||||||
|
core::array<T> m_id_to_value;
|
||||||
|
core::map<T, u32> m_value_to_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Checks if a string contains only supplied characters
|
||||||
|
*/
|
||||||
|
inline bool string_allowed(const std::string &s, const std::string &allowed_chars)
|
||||||
|
{
|
||||||
|
for(u32 i=0; i<s.size(); i++)
|
||||||
|
{
|
||||||
|
bool confirmed = false;
|
||||||
|
for(u32 j=0; j<allowed_chars.size(); j++)
|
||||||
|
{
|
||||||
|
if(s[i] == allowed_chars[j])
|
||||||
|
{
|
||||||
|
confirmed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(confirmed == false)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user