forked from Mirrorlandia_minetest/minetest
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"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\mineral.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\player.cpp"
|
||||
>
|
||||
|
@ -38,18 +38,12 @@ configure_file(
|
||||
"${PROJECT_BINARY_DIR}/cmake_config.h"
|
||||
)
|
||||
|
||||
set(minetest_SRCS
|
||||
guiMainMenu.cpp
|
||||
set(common_SRCS
|
||||
mineral.cpp
|
||||
porting.cpp
|
||||
guiMessageMenu.cpp
|
||||
materials.cpp
|
||||
guiTextInputMenu.cpp
|
||||
guiInventoryMenu.cpp
|
||||
irrlichtwrapper.cpp
|
||||
guiPauseMenu.cpp
|
||||
defaultsettings.cpp
|
||||
mapnode.cpp
|
||||
tile.cpp
|
||||
voxel.cpp
|
||||
mapblockobject.cpp
|
||||
inventory.cpp
|
||||
@ -59,7 +53,6 @@ set(minetest_SRCS
|
||||
filesys.cpp
|
||||
connection.cpp
|
||||
environment.cpp
|
||||
client.cpp
|
||||
server.cpp
|
||||
socket.cpp
|
||||
mapblock.cpp
|
||||
@ -68,34 +61,24 @@ set(minetest_SRCS
|
||||
map.cpp
|
||||
player.cpp
|
||||
utility.cpp
|
||||
main.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
|
||||
porting.cpp
|
||||
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
|
||||
${common_SRCS}
|
||||
servermain.cpp
|
||||
test.cpp
|
||||
)
|
||||
|
||||
include_directories(
|
||||
|
@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include "environment.h"
|
||||
#include "filesys.h"
|
||||
|
||||
Environment::Environment(Map *map, std::ostream &dout):
|
||||
m_dout(dout)
|
||||
@ -192,6 +193,7 @@ void Environment::addPlayer(Player *player)
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
/*
|
||||
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
|
||||
*/
|
||||
#ifndef SERVER
|
||||
@ -201,8 +203,12 @@ void Environment::addPlayer(Player *player)
|
||||
*/
|
||||
assert(!(player->isLocal() == true && getLocalPlayer() != NULL));
|
||||
#endif
|
||||
// If peer id is non-zero, it has to be unique.
|
||||
if(player->peer_id != 0)
|
||||
assert(getPlayer(player->peer_id) == NULL);
|
||||
// Name has to be unique.
|
||||
assert(getPlayer(player->getName()) == NULL);
|
||||
// Add.
|
||||
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
|
||||
void Environment::updateMeshes(v3s16 blockpos)
|
||||
{
|
||||
|
@ -64,6 +64,10 @@ public:
|
||||
core::list<Player*> getPlayers(bool ignore_disconnected);
|
||||
void printPlayers(std::ostream &o);
|
||||
|
||||
void serializePlayers(const std::string &savedir);
|
||||
// This loads players as ServerRemotePlayers
|
||||
void deSerializePlayers(const std::string &savedir);
|
||||
|
||||
#ifndef SERVER
|
||||
void updateMeshes(v3s16 blockpos);
|
||||
void expireMeshes(bool only_daynight_diffed);
|
||||
|
@ -217,7 +217,7 @@ void InventoryList::serialize(std::ostream &os)
|
||||
os<<"\n";
|
||||
}
|
||||
|
||||
os<<"end\n";
|
||||
os<<"EndInventoryList\n";
|
||||
}
|
||||
|
||||
void InventoryList::deSerialize(std::istream &is)
|
||||
@ -238,7 +238,7 @@ void InventoryList::deSerialize(std::istream &is)
|
||||
std::string name;
|
||||
std::getline(iss, name, ' ');
|
||||
|
||||
if(name == "end")
|
||||
if(name == "EndInventoryList")
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -497,7 +497,7 @@ void Inventory::serialize(std::ostream &os)
|
||||
list->serialize(os);
|
||||
}
|
||||
|
||||
os<<"end\n";
|
||||
os<<"EndInventory\n";
|
||||
}
|
||||
|
||||
void Inventory::deSerialize(std::istream &is)
|
||||
@ -514,7 +514,7 @@ void Inventory::deSerialize(std::istream &is)
|
||||
std::string name;
|
||||
std::getline(iss, name, ' ');
|
||||
|
||||
if(name == "end")
|
||||
if(name == "EndInventory")
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -122,10 +122,12 @@ public:
|
||||
#ifndef SERVER
|
||||
video::ITexture * getImage()
|
||||
{
|
||||
if(m_content >= USEFUL_CONTENT_COUNT)
|
||||
/*if(m_content >= USEFUL_CONTENT_COUNT)
|
||||
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
|
||||
std::string getText()
|
||||
@ -250,19 +252,19 @@ public:
|
||||
#ifndef SERVER
|
||||
video::ITexture * getImage()
|
||||
{
|
||||
std::string basename;
|
||||
std::string name;
|
||||
|
||||
if(m_subname == "Stick")
|
||||
basename = porting::getDataPath("stick.png");
|
||||
name = "stick.png";
|
||||
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")
|
||||
basename = porting::getDataPath("lump_of_iron.png");
|
||||
name = "lump_of_iron.png";
|
||||
else
|
||||
basename = porting::getDataPath("cloud.png[[mod:crack3");
|
||||
name = "cloud.png";
|
||||
|
||||
// Get such a texture
|
||||
return g_irrlicht->getTexture(basename);
|
||||
return g_irrlicht->getTexture(name);
|
||||
}
|
||||
#endif
|
||||
std::string getText()
|
||||
@ -330,28 +332,35 @@ public:
|
||||
{
|
||||
std::string basename;
|
||||
if(m_toolname == "WPick")
|
||||
basename = porting::getDataPath("tool_wpick.png").c_str();
|
||||
basename = "tool_wpick.png";
|
||||
else if(m_toolname == "STPick")
|
||||
basename = porting::getDataPath("tool_stpick.png").c_str();
|
||||
basename = "tool_stpick.png";
|
||||
else if(m_toolname == "MesePick")
|
||||
basename = porting::getDataPath("tool_mesepick.png").c_str();
|
||||
// Default to cloud texture
|
||||
basename = "tool_mesepick.png";
|
||||
else
|
||||
basename = porting::getDataPath("cloud.png").c_str();
|
||||
//basename = tile_texture_path_get(TILE_CLOUD);
|
||||
basename = "cloud.png";
|
||||
|
||||
/*
|
||||
Calculate some progress value with sane amount of
|
||||
Calculate a progress value with sane amount of
|
||||
maximum states
|
||||
*/
|
||||
u32 maxprogress = 30;
|
||||
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;
|
||||
std::ostringstream os;
|
||||
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
|
||||
std::ostringstream os;
|
||||
|
@ -17,13 +17,15 @@ void IrrlichtWrapper::Run()
|
||||
*/
|
||||
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();
|
||||
|
||||
dstream<<"got texture request with key="
|
||||
<<request.key<<std::endl;
|
||||
dstream<<"got texture request with"
|
||||
<<" 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.key = request.key;
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
dstream<<"Getting texture directly: spec="
|
||||
<<spec<<std::endl;
|
||||
dstream<<"Getting texture directly: spec.tids[0]="
|
||||
<<spec.tids[0]<<std::endl;
|
||||
|
||||
t = getTextureDirect(spec);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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
|
||||
m_get_texture_queue.add(spec, 0, 0, &result_queue);
|
||||
|
||||
dstream<<"Waiting for texture from main thread: "
|
||||
<<spec<<std::endl;
|
||||
dstream<<"Waiting for texture from main thread: spec.tids[0]="
|
||||
<<spec.tids[0]<<std::endl;
|
||||
|
||||
try
|
||||
{
|
||||
// Wait result for a second
|
||||
GetResult<std::string, video::ITexture*, u8, u8>
|
||||
GetResult<TextureSpec, video::ITexture*, u8, u8>
|
||||
result = result_queue.pop_front(1000);
|
||||
|
||||
// Check that at least something worked OK
|
||||
@ -83,59 +105,115 @@ video::ITexture* IrrlichtWrapper::getTexture(const std::string &spec)
|
||||
return t;
|
||||
}
|
||||
|
||||
/*
|
||||
Non-thread-safe functions
|
||||
*/
|
||||
// Draw a progress bar on the image
|
||||
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 * make_blitname(const std::string &blitted_name,
|
||||
video::ITexture *original,
|
||||
const char *newname, video::IVideoDriver* driver)
|
||||
video::ITexture* IrrlichtWrapper::getTextureDirect(const TextureSpec &spec)
|
||||
{
|
||||
if(original == NULL)
|
||||
// This would result in NULL image
|
||||
if(spec.empty())
|
||||
return NULL;
|
||||
|
||||
// Size of the base image
|
||||
core::dimension2d<u32> dim(16, 16);
|
||||
// Don't generate existing stuff
|
||||
video::ITexture *t = m_texturecache.get(spec);
|
||||
if(t != NULL)
|
||||
{
|
||||
dstream<<"WARNING: Existing stuff requested from "
|
||||
"getTextureDirect()"<<std::endl;
|
||||
return t;
|
||||
}
|
||||
|
||||
video::IVideoDriver* driver = m_device->getVideoDriver();
|
||||
|
||||
/*
|
||||
An image will be built from files and then converted into a texture.
|
||||
*/
|
||||
video::IImage *baseimg = NULL;
|
||||
|
||||
/*
|
||||
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_base(0, 0);
|
||||
core::position2d<s32> pos_to(0,0);
|
||||
// Position to copy the blitted from in the blitted image
|
||||
core::position2d<s32> pos_other(0, 0);
|
||||
|
||||
video::IImage *baseimage = driver->createImage(original, pos_base, dim);
|
||||
assert(baseimage);
|
||||
|
||||
video::IImage *blittedimage = driver->createImageFromFile(porting::getDataPath(blitted_name.c_str()).c_str());
|
||||
assert(blittedimage);
|
||||
|
||||
// Then copy the right part of blittedimage to baseimage
|
||||
|
||||
blittedimage->copyToWithAlpha(baseimage, v2s32(0,0),
|
||||
core::rect<s32>(pos_other, dim),
|
||||
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);
|
||||
|
||||
blittedimage->drop();
|
||||
|
||||
// Create texture from resulting image
|
||||
|
||||
video::ITexture *newtexture = driver->addTexture(newname, baseimage);
|
||||
|
||||
baseimage->drop();
|
||||
|
||||
return newtexture;
|
||||
}
|
||||
|
||||
video::ITexture * make_crack(u16 progression, video::ITexture *original,
|
||||
const char *newname, video::IVideoDriver* driver)
|
||||
{
|
||||
if(original == NULL)
|
||||
return 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
|
||||
@ -145,82 +223,59 @@ video::ITexture * make_crack(u16 progression, video::ITexture *original,
|
||||
// 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),
|
||||
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;
|
||||
}
|
||||
|
||||
/*// DEBUG: Paint some pixels
|
||||
video::SColor c(255,255,0,0);
|
||||
baseimg->setPixel(1,1, c);
|
||||
baseimg->setPixel(1,14, c);
|
||||
baseimg->setPixel(14,1, c);
|
||||
baseimg->setPixel(14,14, c);*/
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
#if 0
|
||||
video::ITexture * make_sidegrass(video::ITexture *original,
|
||||
const char *newname, video::IVideoDriver* driver)
|
||||
void make_progressbar(float value, video::IImage *image)
|
||||
{
|
||||
if(original == NULL)
|
||||
return NULL;
|
||||
if(image == NULL)
|
||||
return;
|
||||
|
||||
// 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();
|
||||
core::dimension2d<u32> size = image->getDimension();
|
||||
|
||||
u32 barheight = 1;
|
||||
u32 barpad_x = 1;
|
||||
@ -242,177 +297,9 @@ video::ITexture * make_progressbar(float value, video::ITexture *original,
|
||||
u32 x = x0 + barpos.X;
|
||||
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 "debug.h"
|
||||
#include "utility.h"
|
||||
#include "texture.h"
|
||||
|
||||
#include <jmutex.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
|
||||
background threads.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
class TextureCache
|
||||
{
|
||||
public:
|
||||
@ -73,12 +74,55 @@ private:
|
||||
core::map<std::string, video::ITexture*> m_textures;
|
||||
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
|
||||
background worker threads.
|
||||
|
||||
Queues tasks to be done in the main thread.
|
||||
|
||||
Also caches texture specification strings to ids and textures.
|
||||
*/
|
||||
|
||||
class IrrlichtWrapper
|
||||
@ -104,29 +148,54 @@ public:
|
||||
}
|
||||
|
||||
/*
|
||||
Path can contain stuff like
|
||||
"/usr/share/minetest/stone.png[[mod:mineral0[[mod:crack3"
|
||||
Format of a texture name:
|
||||
"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:
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
// The id of the thread that can (and has to) use irrlicht directly
|
||||
threadid_t m_main_thread;
|
||||
|
||||
// The irrlicht device
|
||||
JMutex m_device_mutex;
|
||||
IrrlichtDevice *m_device;
|
||||
|
||||
// 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;
|
||||
|
||||
RequestQueue<std::string, video::ITexture*, u8, u8> m_get_texture_queue;
|
||||
// A mapping from texture id to string spec
|
||||
MutexedIdGenerator<std::string> m_namecache;
|
||||
};
|
||||
|
||||
#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:
|
||||
-------------
|
||||
|
||||
- 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:
|
||||
--------------
|
||||
@ -165,6 +168,20 @@ TODO: Make fetching sector's blocks more efficient when rendering
|
||||
|
||||
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:
|
||||
--------------
|
||||
|
||||
@ -281,18 +298,6 @@ TODO: Flowing water to actually contain flow direction information
|
||||
TODO: Remove duplicate lighting implementation from Map (leave
|
||||
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:
|
||||
----------
|
||||
|
||||
@ -360,6 +365,7 @@ Doing now:
|
||||
#include "filesys.h"
|
||||
#include "config.h"
|
||||
#include "guiMainMenu.h"
|
||||
#include "mineral.h"
|
||||
|
||||
IrrlichtWrapper *g_irrlicht;
|
||||
|
||||
@ -1445,7 +1451,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
// C-style stuff initialization
|
||||
initializeMaterialProperties();
|
||||
init_mapnode();
|
||||
|
||||
// Debug handler
|
||||
BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||
@ -1683,7 +1688,8 @@ int main(int argc, char *argv[])
|
||||
*/
|
||||
|
||||
init_content_inventory_texture_paths();
|
||||
//init_tile_textures();
|
||||
init_mapnode(g_irrlicht);
|
||||
init_mineral(g_irrlicht);
|
||||
|
||||
/*
|
||||
GUI stuff
|
||||
@ -2378,7 +2384,7 @@ int main(int argc, char *argv[])
|
||||
bool nodefound = false;
|
||||
v3s16 nodepos;
|
||||
v3s16 neighbourpos;
|
||||
core::aabbox3d<f32> nodefacebox;
|
||||
core::aabbox3d<f32> nodehilightbox;
|
||||
f32 mindistance = BS * 1001;
|
||||
|
||||
v3s16 pos_i = floatToInt(player_position);
|
||||
@ -2470,7 +2476,7 @@ int main(int argc, char *argv[])
|
||||
nodepos = np;
|
||||
neighbourpos = np;
|
||||
mindistance = distance;
|
||||
nodefacebox = box;
|
||||
nodehilightbox = box;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2513,7 +2519,16 @@ int main(int argc, char *argv[])
|
||||
nodepos = np;
|
||||
neighbourpos = np + dirs[i];
|
||||
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
|
||||
} // for dirs
|
||||
@ -2531,15 +2546,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Visualize selection
|
||||
|
||||
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);
|
||||
//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);
|
||||
hilightboxes.push_back(nodehilightbox);
|
||||
|
||||
// Handle digging
|
||||
|
||||
|
@ -263,6 +263,7 @@ void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f p,
|
||||
|
||||
//u8 li = decode_light(light);
|
||||
u8 li = light;
|
||||
//u8 li = 255; //DEBUG
|
||||
|
||||
u8 alpha = tile.alpha;
|
||||
/*u8 alpha = 255;
|
||||
@ -309,15 +310,16 @@ TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir)
|
||||
struct NodeMod mod = n->getValue();
|
||||
if(mod.type == NODEMOD_CHANGECONTENT)
|
||||
{
|
||||
//spec = content_tile(mod.param, face_dir);
|
||||
MapNode mn2(mod.param);
|
||||
spec = mn2.getTile(face_dir);
|
||||
}
|
||||
if(mod.type == NODEMOD_CRACK)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os<<"[[mod:crack"<<mod.param;
|
||||
spec.name += os.str();
|
||||
os<<"[crack"<<mod.param;
|
||||
|
||||
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
|
||||
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)
|
||||
//TimeTaker timer2("updateMesh() mesh building");
|
||||
|
||||
for(u32 i=0; i<fastfaces_new.size(); i++)
|
||||
{
|
||||
FastFace &f = fastfaces_new[i];
|
||||
|
||||
const u16 indices[] = {0,1,2,2,3,0};
|
||||
|
||||
video::ITexture *texture = g_irrlicht->getTexture(f.tile.name);
|
||||
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++)
|
||||
{
|
||||
FastFace &f = fastfaces_new[i];
|
||||
|
||||
const u16 indices[] = {0,1,2,2,3,0};
|
||||
|
||||
video::ITexture *texture = g_irrlicht->getTexture(f.tile.spec);
|
||||
material.setTexture(0, texture);
|
||||
if(f.tile.alpha != 255)
|
||||
material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
||||
else
|
||||
material.MaterialType = video::EMT_SOLID;
|
||||
|
||||
collector.append(material, f.vertices, 4, indices, 6);
|
||||
}
|
||||
@ -691,13 +697,22 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
||||
/*
|
||||
Add special graphics:
|
||||
- torches
|
||||
|
||||
TODO: Optimize by using same meshbuffer for same textures
|
||||
- flowing water
|
||||
*/
|
||||
|
||||
// 0ms
|
||||
//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 y=0; y<MAP_BLOCKSIZE; y++)
|
||||
for(s16 x=0; x<MAP_BLOCKSIZE; x++)
|
||||
@ -751,17 +766,17 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
||||
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
if(dir == v3s16(0,-1,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))
|
||||
material.setTexture(0,
|
||||
g_irrlicht->getTexture(porting::getDataPath("torch_on_ceiling.png").c_str()));
|
||||
g_irrlicht->getTexture("torch_on_ceiling.png"));
|
||||
// For backwards compatibility
|
||||
else if(dir == v3s16(0,0,0))
|
||||
material.setTexture(0,
|
||||
g_irrlicht->getTexture(porting::getDataPath("torch_on_floor.png").c_str()));
|
||||
g_irrlicht->getTexture("torch_on_floor.png"));
|
||||
else
|
||||
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};
|
||||
// Add to mesh collector
|
||||
@ -947,19 +962,9 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
||||
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};
|
||||
// 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());
|
||||
}
|
||||
|
||||
// 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};
|
||||
// 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];
|
||||
|
||||
void init_mapnode()
|
||||
ContentFeatures & content_features(u8 i)
|
||||
{
|
||||
return g_content_features[i];
|
||||
}
|
||||
|
||||
void init_mapnode(IrrlichtWrapper *irrlicht)
|
||||
{
|
||||
u8 i;
|
||||
ContentFeatures *f = NULL;
|
||||
|
||||
i = CONTENT_STONE;
|
||||
f = &g_content_features[i];
|
||||
f->setAllTextures("stone.png");
|
||||
f->setAllTextures(irrlicht->getTextureId("stone.png"));
|
||||
f->param_type = CPT_MINERAL;
|
||||
f->is_ground_content = true;
|
||||
|
||||
i = CONTENT_GRASS;
|
||||
f = &g_content_features[i];
|
||||
//f->setAllTextures("mud.png[[mod:sidegrass");
|
||||
f->setAllTextures("mud.png[[mod:blitname:grass_side.png");
|
||||
f->setTexture(0, "grass.png");
|
||||
f->setTexture(1, "mud.png");
|
||||
f->setInventoryImage("grass.png");
|
||||
f->setAllTextures(TextureSpec(irrlicht->getTextureId("mud.png"),
|
||||
irrlicht->getTextureId("grass_side.png")));
|
||||
f->setTexture(0, irrlicht->getTextureId("grass.png"));
|
||||
f->setTexture(1, irrlicht->getTextureId("mud.png"));
|
||||
f->setInventoryTexture(irrlicht->getTextureId("grass.png"));
|
||||
f->param_type = CPT_MINERAL;
|
||||
f->is_ground_content = true;
|
||||
|
||||
i = CONTENT_GRASS_FOOTSTEPS;
|
||||
f = &g_content_features[i];
|
||||
//f->setAllTextures("mud.png[[mod:sidegrass");
|
||||
f->setAllTextures("mud.png[[mod:blitname:grass_side.png");
|
||||
f->setTexture(0, "grass_footsteps.png");
|
||||
f->setTexture(1, "mud.png");
|
||||
f->setInventoryImage("grass_footsteps.png");
|
||||
f->setAllTextures(TextureSpec(irrlicht->getTextureId("mud.png"),
|
||||
irrlicht->getTextureId("grass_side.png")));
|
||||
f->setTexture(0, irrlicht->getTextureId("grass_footsteps.png"));
|
||||
f->setTexture(1, irrlicht->getTextureId("mud.png"));
|
||||
f->setInventoryTexture(irrlicht->getTextureId("grass_footsteps.png"));
|
||||
f->param_type = CPT_MINERAL;
|
||||
f->is_ground_content = true;
|
||||
|
||||
i = CONTENT_MUD;
|
||||
f = &g_content_features[i];
|
||||
f->setAllTextures("mud.png");
|
||||
f->setAllTextures(irrlicht->getTextureId("mud.png"));
|
||||
f->param_type = CPT_MINERAL;
|
||||
f->is_ground_content = true;
|
||||
|
||||
i = CONTENT_SAND;
|
||||
f = &g_content_features[i];
|
||||
f->setAllTextures("mud.png");
|
||||
f->setAllTextures(irrlicht->getTextureId("mud.png"));
|
||||
f->param_type = CPT_MINERAL;
|
||||
f->is_ground_content = true;
|
||||
|
||||
i = CONTENT_TREE;
|
||||
f = &g_content_features[i];
|
||||
f->setAllTextures("tree.png");
|
||||
f->setAllTextures(irrlicht->getTextureId("tree.png"));
|
||||
f->param_type = CPT_MINERAL;
|
||||
f->is_ground_content = true;
|
||||
|
||||
i = CONTENT_LEAVES;
|
||||
f = &g_content_features[i];
|
||||
f->setAllTextures("leaves.png");
|
||||
f->setAllTextures(irrlicht->getTextureId("leaves.png"));
|
||||
f->param_type = CPT_MINERAL;
|
||||
f->is_ground_content = true;
|
||||
|
||||
i = CONTENT_COALSTONE;
|
||||
f = &g_content_features[i];
|
||||
f->translate_to = new MapNode(CONTENT_STONE, MINERAL_COAL);
|
||||
/*f->setAllTextures("coalstone.png");
|
||||
/*f->setAllTextures(irrlicht->getTextureId("coalstone.png"));
|
||||
f->is_ground_content = true;*/
|
||||
|
||||
i = CONTENT_WOOD;
|
||||
f = &g_content_features[i];
|
||||
f->setAllTextures("wood.png");
|
||||
f->setAllTextures(irrlicht->getTextureId("wood.png"));
|
||||
f->is_ground_content = true;
|
||||
|
||||
i = CONTENT_MESE;
|
||||
f = &g_content_features[i];
|
||||
f->setAllTextures("mese.png");
|
||||
f->setAllTextures(irrlicht->getTextureId("mese.png"));
|
||||
f->is_ground_content = true;
|
||||
|
||||
i = CONTENT_CLOUD;
|
||||
f = &g_content_features[i];
|
||||
f->setAllTextures("cloud.png");
|
||||
f->setAllTextures(irrlicht->getTextureId("cloud.png"));
|
||||
f->is_ground_content = true;
|
||||
|
||||
i = CONTENT_AIR;
|
||||
@ -120,7 +125,7 @@ void init_mapnode()
|
||||
|
||||
i = CONTENT_WATER;
|
||||
f = &g_content_features[i];
|
||||
f->setInventoryImage("water.png");
|
||||
f->setInventoryTexture(irrlicht->getTextureId("water.png"));
|
||||
f->param_type = CPT_LIGHT;
|
||||
f->light_propagates = true;
|
||||
f->solidness = 0; // Drawn separately, makes no faces
|
||||
@ -132,8 +137,8 @@ void init_mapnode()
|
||||
|
||||
i = CONTENT_WATERSOURCE;
|
||||
f = &g_content_features[i];
|
||||
f->setTexture(0, "water.png", WATER_ALPHA);
|
||||
f->setInventoryImage("water.png");
|
||||
f->setTexture(0, irrlicht->getTextureId("water.png"), WATER_ALPHA);
|
||||
f->setInventoryTexture(irrlicht->getTextureId("water.png"));
|
||||
f->param_type = CPT_LIGHT;
|
||||
f->light_propagates = true;
|
||||
f->solidness = 1;
|
||||
@ -145,7 +150,7 @@ void init_mapnode()
|
||||
|
||||
i = CONTENT_TORCH;
|
||||
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->light_propagates = true;
|
||||
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)
|
||||
{
|
||||
u8 mineral = param & 0x1f;
|
||||
const char *ts = mineral_block_texture(mineral);
|
||||
if(ts[0] != 0)
|
||||
{
|
||||
spec.name += "[[mod:blitname:";
|
||||
spec.name += ts;
|
||||
}
|
||||
// Add mineral block texture
|
||||
textureid_t tid = mineral_block_texture(mineral);
|
||||
if(tid != 0)
|
||||
spec.spec.addTid(tid);
|
||||
}
|
||||
|
||||
return spec;
|
||||
@ -206,14 +209,15 @@ u8 MapNode::getMineral()
|
||||
}
|
||||
|
||||
// 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()
|
||||
{
|
||||
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_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 "serialization.h"
|
||||
#include "tile.h"
|
||||
#include "irrlichtwrapper.h"
|
||||
|
||||
// Initializes all kind of stuff in here.
|
||||
// Doesn't depend on anything else.
|
||||
// Many things depend on this.
|
||||
void init_mapnode();
|
||||
/*
|
||||
Initializes all kind of stuff in here.
|
||||
Many things depend on this.
|
||||
|
||||
irrlicht: Used for getting texture ids.
|
||||
*/
|
||||
void init_mapnode(IrrlichtWrapper *irrlicht);
|
||||
|
||||
// Initializes g_content_inventory_texture_paths
|
||||
void init_content_inventory_texture_paths();
|
||||
@ -129,7 +133,8 @@ struct ContentFeatures
|
||||
*/
|
||||
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 light_propagates;
|
||||
@ -162,39 +167,42 @@ struct 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++)
|
||||
{
|
||||
tiles[i].name = porting::getDataPath(imgname.c_str());
|
||||
tiles[i].spec = spec;
|
||||
tiles[i].alpha = alpha;
|
||||
}
|
||||
|
||||
// Set this too so it can be left as is most times
|
||||
if(inventory_image_path == "")
|
||||
inventory_image_path = porting::getDataPath(imgname.c_str());
|
||||
/*if(inventory_image_path == "")
|
||||
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;
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}*/
|
||||
};
|
||||
|
||||
// Initialized by init_mapnode()
|
||||
extern struct ContentFeatures g_content_features[256];
|
||||
|
||||
inline ContentFeatures & content_features(u8 i)
|
||||
{
|
||||
return g_content_features[i];
|
||||
}
|
||||
|
||||
extern const char * g_content_inventory_texture_paths[USEFUL_CONTENT_COUNT];
|
||||
/*
|
||||
Call this to access the ContentFeature list
|
||||
*/
|
||||
ContentFeatures & content_features(u8 i);
|
||||
|
||||
/*
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@ -214,7 +222,7 @@ inline bool light_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);
|
||||
}
|
||||
|
||||
@ -228,7 +236,7 @@ inline bool sunlight_propagates_content(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
|
||||
if(m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER)
|
||||
return 0;
|
||||
@ -241,28 +249,28 @@ inline u8 content_solidness(u8 m)
|
||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||
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);
|
||||
}
|
||||
|
||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||
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);
|
||||
}
|
||||
|
||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||
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);
|
||||
}
|
||||
|
||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||
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);
|
||||
}
|
||||
|
||||
@ -279,21 +287,21 @@ inline u8 make_liquid_flowing(u8 m)
|
||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||
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);
|
||||
}
|
||||
|
||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||
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);
|
||||
}
|
||||
|
||||
// NOTE: Don't use, use "content_features(m).whatever" instead
|
||||
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);
|
||||
}
|
||||
|
||||
@ -303,7 +311,7 @@ inline bool content_buildable_to(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
|
||||
MapNode *translate_to = g_content_features[d].translate_to;
|
||||
MapNode *translate_to = content_features(d).translate_to;
|
||||
if(translate_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
|
||||
|
||||
#include "inventory.h"
|
||||
#include "texture.h"
|
||||
#include "irrlichtwrapper.h"
|
||||
|
||||
/*
|
||||
Minerals
|
||||
@ -29,22 +31,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
type param.
|
||||
*/
|
||||
|
||||
// Caches textures
|
||||
void init_mineral(IrrlichtWrapper *irrlicht);
|
||||
|
||||
#define MINERAL_NONE 0
|
||||
#define MINERAL_COAL 1
|
||||
#define MINERAL_IRON 2
|
||||
|
||||
inline const char * mineral_block_texture(u8 mineral)
|
||||
{
|
||||
switch(mineral)
|
||||
{
|
||||
case MINERAL_COAL:
|
||||
return "mineral_coal.png";
|
||||
case MINERAL_IRON:
|
||||
return "mineral_iron.png";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
#define MINERAL_COUNT 3
|
||||
|
||||
textureid_t mineral_block_texture(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 "connection.h"
|
||||
#include "constants.h"
|
||||
#include "utility.h"
|
||||
|
||||
Player::Player():
|
||||
touching_ground(false),
|
||||
@ -34,15 +35,21 @@ Player::Player():
|
||||
m_position(0,0,0)
|
||||
{
|
||||
updateName("<not set>");
|
||||
inventory.addList("main", PLAYER_INVENTORY_SIZE);
|
||||
inventory.addList("craft", 9);
|
||||
inventory.addList("craftresult", 1);
|
||||
resetInventory();
|
||||
}
|
||||
|
||||
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
|
||||
void Player::accelerate(v3f target_speed, f32 max_increase)
|
||||
{
|
||||
@ -80,6 +87,50 @@ void Player::accelerate(v3f target_speed, f32 max_increase)
|
||||
#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
|
||||
*/
|
||||
|
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_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.,"
|
||||
|
||||
class Map;
|
||||
|
||||
class Player
|
||||
@ -37,6 +39,8 @@ public:
|
||||
Player();
|
||||
virtual ~Player();
|
||||
|
||||
void resetInventory();
|
||||
|
||||
//void move(f32 dtime, Map &map);
|
||||
virtual void move(f32 dtime, Map &map) = 0;
|
||||
|
||||
@ -101,6 +105,14 @@ public:
|
||||
/*virtual bool isClientConnected() { return false; }
|
||||
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 in_water;
|
||||
|
||||
@ -119,8 +131,6 @@ protected:
|
||||
class ServerRemotePlayer : public Player
|
||||
{
|
||||
public:
|
||||
/*ServerRemotePlayer(bool client_connected):
|
||||
m_client_connected(client_connected)*/
|
||||
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:
|
||||
};
|
||||
|
||||
@ -252,7 +250,7 @@ private:
|
||||
v3f m_showpos;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // !SERVER
|
||||
|
||||
#ifndef SERVER
|
||||
struct PlayerControl
|
||||
|
194
src/server.cpp
194
src/server.cpp
@ -1000,7 +1000,8 @@ Server::Server(
|
||||
m_time_of_day(9000),
|
||||
m_time_counter(0),
|
||||
m_time_of_day_send_timer(0),
|
||||
m_uptime(0)
|
||||
m_uptime(0),
|
||||
m_mapsavedir(mapsavedir)
|
||||
{
|
||||
//m_flowwater_timer = 0.0;
|
||||
m_liquid_transform_timer = 0.0;
|
||||
@ -1013,10 +1014,16 @@ Server::Server(
|
||||
m_con_mutex.Init();
|
||||
m_step_dtime_mutex.Init();
|
||||
m_step_dtime = 0.0;
|
||||
|
||||
// Load players
|
||||
m_env.deSerializePlayers(m_mapsavedir);
|
||||
}
|
||||
|
||||
Server::~Server()
|
||||
{
|
||||
// Save players
|
||||
m_env.serializePlayers(m_mapsavedir);
|
||||
|
||||
// Stop threads
|
||||
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
|
||||
{
|
||||
float &counter = m_print_info_timer;
|
||||
@ -1476,6 +1407,9 @@ void Server::AsyncRunStep()
|
||||
dout_server<<"Server: Unloaded "<<deleted_count
|
||||
<<" 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 = 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(player == NULL)
|
||||
{
|
||||
@ -2950,7 +2894,7 @@ void Server::SendInventory(u16 peer_id)
|
||||
if(!found)
|
||||
{
|
||||
ItemSpec specs[9];
|
||||
specs[0] = ItemSpec(ITEM_CRAFT, "Coal");
|
||||
specs[0] = ItemSpec(ITEM_CRAFT, "lump_of_coal");
|
||||
specs[3] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||
if(checkItemCombination(items, specs))
|
||||
{
|
||||
@ -3147,6 +3091,50 @@ RemoteClient* Server::getClient(u16 peer_id)
|
||||
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,
|
||||
u16 peer_id)
|
||||
{
|
||||
@ -3162,8 +3150,16 @@ Player *Server::emergePlayer(const char *name, const char *password,
|
||||
dstream<<"emergePlayer(): Player already connected"<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Got one.
|
||||
player->peer_id = peer_id;
|
||||
|
||||
// Reset inventory to creative if in creative mode
|
||||
if(g_settings.getBool("creative_mode"))
|
||||
{
|
||||
setCreativeInventory(player);
|
||||
}
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
@ -3271,51 +3267,15 @@ Player *Server::emergePlayer(const char *name, const char *password,
|
||||
|
||||
if(g_settings.getBool("creative_mode"))
|
||||
{
|
||||
// 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)
|
||||
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);
|
||||
}
|
||||
setCreativeInventory(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
/*{
|
||||
InventoryItem *item = new ToolItem("WPick", 32000);
|
||||
void* r = player->inventory.addItem("main", item);
|
||||
assert(r == NULL);
|
||||
}
|
||||
}*/
|
||||
/*{
|
||||
InventoryItem *item = new MaterialItem(CONTENT_MESE, 6);
|
||||
void* r = player->inventory.addItem("main", item);
|
||||
|
@ -508,6 +508,8 @@ private:
|
||||
|
||||
Queue<PeerChange> m_peer_change_queue;
|
||||
|
||||
std::string m_mapsavedir;
|
||||
|
||||
friend class EmergeThread;
|
||||
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 "utility.h"
|
||||
#include "texture.h"
|
||||
#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
|
||||
{
|
||||
TileSpec():
|
||||
@ -52,5 +70,6 @@ struct TileSpec
|
||||
std::string name;
|
||||
u8 alpha;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
187
src/utility.h
187
src/utility.h
@ -760,17 +760,20 @@ class Settings
|
||||
{
|
||||
public:
|
||||
|
||||
// Returns false on EOF
|
||||
bool parseConfigObject(std::istream &is)
|
||||
void writeLines(std::ostream &os)
|
||||
{
|
||||
if(is.eof())
|
||||
return false;
|
||||
|
||||
// NOTE: This function will be expanded to allow multi-line settings
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
//dstream<<"got line: \""<<line<<"\""<<std::endl;
|
||||
for(core::map<std::string, std::string>::Iterator
|
||||
i = m_settings.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
std::string name = i.getNode()->getKey();
|
||||
std::string value = i.getNode()->getValue();
|
||||
os<<name<<" = "<<value<<"\n";
|
||||
}
|
||||
}
|
||||
|
||||
bool parseConfigLine(const std::string &line)
|
||||
{
|
||||
std::string trimmedline = trim(line);
|
||||
|
||||
// Ignore comments
|
||||
@ -798,6 +801,23 @@ public:
|
||||
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
|
||||
|
||||
@ -1089,10 +1109,7 @@ public:
|
||||
|
||||
float getFloat(std::string name)
|
||||
{
|
||||
float f;
|
||||
std::istringstream vis(get(name));
|
||||
vis>>f;
|
||||
return f;
|
||||
return stof(get(name));
|
||||
}
|
||||
|
||||
u16 getU16(std::string name)
|
||||
@ -1128,6 +1145,34 @@ public:
|
||||
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()
|
||||
{
|
||||
m_settings.clear();
|
||||
@ -1628,5 +1673,121 @@ private:
|
||||
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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user