WIP node metadata, node timers

This commit is contained in:
Kahrl 2012-03-19 01:08:04 +01:00 committed by Perttu Ahola
parent 67059e1932
commit 704782c95b
19 changed files with 788 additions and 1386 deletions

@ -177,6 +177,7 @@ set(common_SRCS
content_mapnode.cpp
collision.cpp
nodemetadata.cpp
nodetimer.cpp
serverobject.cpp
noise.cpp
porting.cpp

@ -1,6 +1,6 @@
/*
Minetest-c55
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2010-2012 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
@ -18,15 +18,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include "content_nodemeta.h"
#include <map>
#include "inventory.h"
#include "log.h"
#include "utility.h"
#include "craftdef.h"
#include "gamedef.h"
class Inventory;
#define NODEMETA_GENERIC 1
#define NODEMETA_SIGN 14
@ -34,809 +28,149 @@ class Inventory;
#define NODEMETA_FURNACE 16
#define NODEMETA_LOCKABLE_CHEST 17
core::map<u16, NodeMetadata::Factory> NodeMetadata::m_types;
core::map<std::string, NodeMetadata::Factory2> NodeMetadata::m_names;
// Returns true if node timer must be set
static bool content_nodemeta_deserialize_legacy_body(
std::istream &is, s16 id, NodeMetadata *meta)
{
meta->clear();
class SignNodeMetadata : public NodeMetadata
{
public:
SignNodeMetadata(IGameDef *gamedef, std::string text);
//~SignNodeMetadata();
virtual u16 typeId() const;
virtual const char* typeName() const
{ return "sign"; }
static NodeMetadata* create(std::istream &is, IGameDef *gamedef);
static NodeMetadata* create(IGameDef *gamedef);
virtual NodeMetadata* clone(IGameDef *gamedef);
virtual void serializeBody(std::ostream &os);
virtual std::string infoText();
virtual bool allowsTextInput(){ return true; }
virtual std::string getText(){ return m_text; }
virtual void setText(const std::string &t){ m_text = t; }
private:
std::string m_text;
};
class ChestNodeMetadata : public NodeMetadata
{
public:
ChestNodeMetadata(IGameDef *gamedef);
~ChestNodeMetadata();
virtual u16 typeId() const;
virtual const char* typeName() const
{ return "chest"; }
static NodeMetadata* create(std::istream &is, IGameDef *gamedef);
static NodeMetadata* create(IGameDef *gamedef);
virtual NodeMetadata* clone(IGameDef *gamedef);
virtual void serializeBody(std::ostream &os);
virtual std::string infoText();
virtual Inventory* getInventory() {return m_inventory;}
virtual bool nodeRemovalDisabled();
virtual std::string getInventoryDrawSpecString();
private:
Inventory *m_inventory;
};
class LockingChestNodeMetadata : public NodeMetadata
{
public:
LockingChestNodeMetadata(IGameDef *gamedef);
~LockingChestNodeMetadata();
virtual u16 typeId() const;
virtual const char* typeName() const
{ return "locked_chest"; }
static NodeMetadata* create(std::istream &is, IGameDef *gamedef);
static NodeMetadata* create(IGameDef *gamedef);
virtual NodeMetadata* clone(IGameDef *gamedef);
virtual void serializeBody(std::ostream &os);
virtual std::string infoText();
virtual Inventory* getInventory() {return m_inventory;}
virtual bool nodeRemovalDisabled();
virtual std::string getInventoryDrawSpecString();
virtual std::string getOwner(){ return m_text; }
virtual void setOwner(std::string t){ m_text = t; }
private:
Inventory *m_inventory;
std::string m_text;
};
class FurnaceNodeMetadata : public NodeMetadata
{
public:
FurnaceNodeMetadata(IGameDef *gamedef);
~FurnaceNodeMetadata();
virtual u16 typeId() const;
virtual const char* typeName() const
{ return "furnace"; }
virtual NodeMetadata* clone(IGameDef *gamedef);
static NodeMetadata* create(std::istream &is, IGameDef *gamedef);
static NodeMetadata* create(IGameDef *gamedef);
virtual void serializeBody(std::ostream &os);
virtual std::string infoText();
virtual Inventory* getInventory() {return m_inventory;}
virtual void inventoryModified();
virtual bool step(float dtime);
virtual bool nodeRemovalDisabled();
virtual std::string getInventoryDrawSpecString();
protected:
bool getCookResult(bool remove, std::string &cookresult, float &cooktime);
bool getBurnResult(bool remove, float &burntime);
private:
Inventory *m_inventory;
std::string m_infotext;
float m_step_accumulator;
float m_fuel_totaltime;
float m_fuel_time;
float m_src_totaltime;
float m_src_time;
};
/*
SignNodeMetadata
*/
// Prototype
SignNodeMetadata proto_SignNodeMetadata(NULL, "");
SignNodeMetadata::SignNodeMetadata(IGameDef *gamedef, std::string text):
NodeMetadata(gamedef),
m_text(text)
{
NodeMetadata::registerType(typeId(), typeName(), create, create);
}
u16 SignNodeMetadata::typeId() const
{
return NODEMETA_SIGN;
}
NodeMetadata* SignNodeMetadata::create(std::istream &is, IGameDef *gamedef)
{
std::string text = deSerializeString(is);
return new SignNodeMetadata(gamedef, text);
}
NodeMetadata* SignNodeMetadata::create(IGameDef *gamedef)
{
return new SignNodeMetadata(gamedef, "");
}
NodeMetadata* SignNodeMetadata::clone(IGameDef *gamedef)
{
return new SignNodeMetadata(gamedef, m_text);
}
void SignNodeMetadata::serializeBody(std::ostream &os)
{
os<<serializeString(m_text);
}
std::string SignNodeMetadata::infoText()
{
return std::string("\"")+m_text+"\"";
}
/*
ChestNodeMetadata
*/
// Prototype
ChestNodeMetadata proto_ChestNodeMetadata(NULL);
ChestNodeMetadata::ChestNodeMetadata(IGameDef *gamedef):
NodeMetadata(gamedef)
{
NodeMetadata::registerType(typeId(), typeName(), create, create);
m_inventory = NULL;
}
ChestNodeMetadata::~ChestNodeMetadata()
{
delete m_inventory;
}
u16 ChestNodeMetadata::typeId() const
{
return NODEMETA_CHEST;
}
NodeMetadata* ChestNodeMetadata::create(std::istream &is, IGameDef *gamedef)
{
ChestNodeMetadata *d = new ChestNodeMetadata(gamedef);
d->m_inventory = new Inventory(gamedef->idef());
d->m_inventory->deSerialize(is);
return d;
}
NodeMetadata* ChestNodeMetadata::create(IGameDef *gamedef)
{
ChestNodeMetadata *d = new ChestNodeMetadata(gamedef);
d->m_inventory = new Inventory(gamedef->idef());
d->m_inventory->addList("0", 8*4);
return d;
}
NodeMetadata* ChestNodeMetadata::clone(IGameDef *gamedef)
{
ChestNodeMetadata *d = new ChestNodeMetadata(gamedef);
d->m_inventory = new Inventory(*m_inventory);
return d;
}
void ChestNodeMetadata::serializeBody(std::ostream &os)
{
m_inventory->serialize(os);
}
std::string ChestNodeMetadata::infoText()
{
return "Chest";
}
bool ChestNodeMetadata::nodeRemovalDisabled()
{
/*
Disable removal if chest contains something
*/
InventoryList *list = m_inventory->getList("0");
if(list == NULL)
return false;
if(list->getUsedSlots() == 0)
return false;
return true;
}
std::string ChestNodeMetadata::getInventoryDrawSpecString()
{
return
"invsize[8,9;]"
"list[current_name;0;0,0;8,4;]"
"list[current_player;main;0,5;8,4;]";
}
/*
LockingChestNodeMetadata
*/
// Prototype
LockingChestNodeMetadata proto_LockingChestNodeMetadata(NULL);
LockingChestNodeMetadata::LockingChestNodeMetadata(IGameDef *gamedef):
NodeMetadata(gamedef)
{
NodeMetadata::registerType(typeId(), typeName(), create, create);
m_inventory = NULL;
}
LockingChestNodeMetadata::~LockingChestNodeMetadata()
{
delete m_inventory;
}
u16 LockingChestNodeMetadata::typeId() const
{
return NODEMETA_LOCKABLE_CHEST;
}
NodeMetadata* LockingChestNodeMetadata::create(std::istream &is, IGameDef *gamedef)
{
LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef);
d->setOwner(deSerializeString(is));
d->m_inventory = new Inventory(gamedef->idef());
d->m_inventory->deSerialize(is);
return d;
}
NodeMetadata* LockingChestNodeMetadata::create(IGameDef *gamedef)
{
LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef);
d->m_inventory = new Inventory(gamedef->idef());
d->m_inventory->addList("0", 8*4);
return d;
}
NodeMetadata* LockingChestNodeMetadata::clone(IGameDef *gamedef)
{
LockingChestNodeMetadata *d = new LockingChestNodeMetadata(gamedef);
d->m_inventory = new Inventory(*m_inventory);
return d;
}
void LockingChestNodeMetadata::serializeBody(std::ostream &os)
{
os<<serializeString(m_text);
m_inventory->serialize(os);
}
std::string LockingChestNodeMetadata::infoText()
{
return "Locking Chest";
}
bool LockingChestNodeMetadata::nodeRemovalDisabled()
{
/*
Disable removal if chest contains something
*/
InventoryList *list = m_inventory->getList("0");
if(list == NULL)
return false;
if(list->getUsedSlots() == 0)
return false;
return true;
}
std::string LockingChestNodeMetadata::getInventoryDrawSpecString()
{
return
"invsize[8,9;]"
"list[current_name;0;0,0;8,4;]"
"list[current_player;main;0,5;8,4;]";
}
/*
FurnaceNodeMetadata
*/
// Prototype
FurnaceNodeMetadata proto_FurnaceNodeMetadata(NULL);
FurnaceNodeMetadata::FurnaceNodeMetadata(IGameDef *gamedef):
NodeMetadata(gamedef)
{
NodeMetadata::registerType(typeId(), typeName(), create, create);
m_inventory = NULL;
m_infotext = "Furnace is inactive";
m_step_accumulator = 0;
m_fuel_totaltime = 0;
m_fuel_time = 0;
m_src_totaltime = 0;
m_src_time = 0;
}
FurnaceNodeMetadata::~FurnaceNodeMetadata()
{
delete m_inventory;
}
u16 FurnaceNodeMetadata::typeId() const
{
return NODEMETA_FURNACE;
}
NodeMetadata* FurnaceNodeMetadata::clone(IGameDef *gamedef)
{
FurnaceNodeMetadata *d = new FurnaceNodeMetadata(m_gamedef);
d->m_inventory = new Inventory(*m_inventory);
return d;
}
NodeMetadata* FurnaceNodeMetadata::create(std::istream &is, IGameDef *gamedef)
{
FurnaceNodeMetadata *d = new FurnaceNodeMetadata(gamedef);
d->m_inventory = new Inventory(gamedef->idef());
d->m_inventory->deSerialize(is);
int temp = 0;
is>>temp;
d->m_fuel_totaltime = (float)temp/10;
temp = 0;
is>>temp;
d->m_fuel_time = (float)temp/10;
temp = 0;
is>>temp;
d->m_src_totaltime = (float)temp/10;
temp = 0;
is>>temp;
d->m_src_time = (float)temp/10;
if(is.eof())
if(id == NODEMETA_GENERIC) // GenericNodeMetadata (0.4-dev)
{
// Old furnaces didn't serialize src_totaltime and src_time
d->m_src_totaltime = 0;
d->m_src_time = 0;
d->m_infotext = "";
}
else
{
// New furnaces also serialize the infotext (so that the
// client doesn't need to have the list of cooking recipes).
d->m_infotext = deSerializeJsonString(is);
}
meta->getInventory()->deSerialize(is);
deSerializeLongString(is); // m_text
deSerializeString(is); // m_owner
return d;
}
NodeMetadata* FurnaceNodeMetadata::create(IGameDef *gamedef)
{
FurnaceNodeMetadata *d = new FurnaceNodeMetadata(gamedef);
d->m_inventory = new Inventory(gamedef->idef());
d->m_inventory->addList("fuel", 1);
d->m_inventory->addList("src", 1);
d->m_inventory->addList("dst", 4);
return d;
}
void FurnaceNodeMetadata::serializeBody(std::ostream &os)
{
m_inventory->serialize(os);
os<<itos(m_fuel_totaltime*10)<<" ";
os<<itos(m_fuel_time*10)<<" ";
os<<itos(m_src_totaltime*10)<<" ";
os<<itos(m_src_time*10)<<" ";
os<<serializeJsonString(m_infotext);
}
std::string FurnaceNodeMetadata::infoText()
{
return m_infotext;
}
bool FurnaceNodeMetadata::nodeRemovalDisabled()
{
/*
Disable removal if furnace is not empty
*/
InventoryList *list[3] = {m_inventory->getList("src"),
m_inventory->getList("dst"), m_inventory->getList("fuel")};
for(int i = 0; i < 3; i++) {
if(list[i] == NULL)
continue;
if(list[i]->getUsedSlots() == 0)
continue;
return true;
}
return false;
}
void FurnaceNodeMetadata::inventoryModified()
{
infostream<<"Furnace inventory modification callback"<<std::endl;
}
bool FurnaceNodeMetadata::step(float dtime)
{
if(dtime > 60.0)
infostream<<"Furnace stepping a long time ("<<dtime<<")"<<std::endl;
InventoryList *dst_list = m_inventory->getList("dst");
assert(dst_list);
// Update at a fixed frequency
const float interval = 2.0;
m_step_accumulator += dtime;
bool changed = false;
while(m_step_accumulator > interval)
{
m_step_accumulator -= interval;
dtime = interval;
//infostream<<"Furnace step dtime="<<dtime<<std::endl;
bool changed_this_loop = false;
// Check
// 1. if the source item is cookable
// 2. if there is room for the cooked item
std::string cookresult;
float cooktime;
bool cookable = getCookResult(false, cookresult, cooktime);
ItemStack cookresult_item;
bool room_available = false;
if(cookable)
{
cookresult_item.deSerialize(cookresult, m_gamedef->idef());
room_available = dst_list->roomForItem(cookresult_item);
}
// Step fuel time
bool burning = (m_fuel_time < m_fuel_totaltime);
if(burning)
{
changed_this_loop = true;
m_fuel_time += dtime;
}
std::string infotext;
if(room_available)
{
float burntime;
if(burning)
{
changed_this_loop = true;
m_src_time += dtime;
m_src_totaltime = cooktime;
infotext = "Furnace is cooking";
}
else if(getBurnResult(true, burntime))
{
// Fuel inserted
changed_this_loop = true;
m_fuel_time = 0;
m_fuel_totaltime = burntime;
//m_src_time += dtime;
//m_src_totaltime = cooktime;
infotext = "Furnace is cooking";
}
else
{
m_src_time = 0;
m_src_totaltime = 0;
infotext = "Furnace is out of fuel";
}
if(m_src_totaltime > 0.001 && m_src_time >= m_src_totaltime)
{
// One item fully cooked
changed_this_loop = true;
dst_list->addItem(cookresult_item);
getCookResult(true, cookresult, cooktime); // decrement source
m_src_totaltime = 0;
m_src_time = 0;
}
}
else
{
// Not cookable or no room available
m_src_totaltime = 0;
m_src_time = 0;
if(cookable)
infotext = "Furnace is overloaded";
else if(burning)
infotext = "Furnace is active";
else
{
infotext = "Furnace is inactive";
m_fuel_totaltime = 0;
m_fuel_time = 0;
}
}
// Do this so it doesn't always show (0%) for weak fuel
if(m_fuel_totaltime > 3) {
infotext += " (";
infotext += itos(m_fuel_time/m_fuel_totaltime*100);
infotext += "%)";
}
if(infotext != m_infotext)
{
m_infotext = infotext;
changed_this_loop = true;
}
if(burning && m_fuel_time >= m_fuel_totaltime)
{
m_fuel_time = 0;
m_fuel_totaltime = 0;
}
if(changed_this_loop)
{
changed = true;
}
else
{
m_step_accumulator = 0;
break;
}
}
return changed;
}
std::string FurnaceNodeMetadata::getInventoryDrawSpecString()
{
return
"invsize[8,9;]"
"list[current_name;fuel;2,3;1,1;]"
"list[current_name;src;2,1;1,1;]"
"list[current_name;dst;5,1;2,2;]"
"list[current_player;main;0,5;8,4;]";
}
bool FurnaceNodeMetadata::getCookResult(bool remove,
std::string &cookresult, float &cooktime)
{
std::vector<ItemStack> items;
InventoryList *src_list = m_inventory->getList("src");
assert(src_list);
items.push_back(src_list->getItem(0));
CraftInput ci(CRAFT_METHOD_COOKING, 1, items);
CraftOutput co;
bool found = m_gamedef->getCraftDefManager()->getCraftResult(
ci, co, remove, m_gamedef);
if(remove)
src_list->changeItem(0, ci.items[0]);
cookresult = co.item;
cooktime = co.time;
return found;
}
bool FurnaceNodeMetadata::getBurnResult(bool remove, float &burntime)
{
std::vector<ItemStack> items;
InventoryList *fuel_list = m_inventory->getList("fuel");
assert(fuel_list);
items.push_back(fuel_list->getItem(0));
CraftInput ci(CRAFT_METHOD_FUEL, 1, items);
CraftOutput co;
bool found = m_gamedef->getCraftDefManager()->getCraftResult(
ci, co, remove, m_gamedef);
if(remove)
fuel_list->changeItem(0, ci.items[0]);
burntime = co.time;
return found;
}
/*
GenericNodeMetadata
*/
class GenericNodeMetadata : public NodeMetadata
{
private:
Inventory *m_inventory;
std::string m_text;
std::string m_owner;
std::string m_infotext;
std::string m_inventorydrawspec;
bool m_allow_text_input;
bool m_removal_disabled;
bool m_enforce_owner;
bool m_inventory_modified;
bool m_text_modified;
std::map<std::string, std::string> m_stringvars;
public:
u16 typeId() const
{
return NODEMETA_GENERIC;
}
const char* typeName() const
{
return "generic";
}
GenericNodeMetadata(IGameDef *gamedef):
NodeMetadata(gamedef),
m_inventory(NULL),
m_text(""),
m_owner(""),
m_infotext("GenericNodeMetadata"),
m_inventorydrawspec(""),
m_allow_text_input(false),
m_removal_disabled(false),
m_enforce_owner(false),
m_inventory_modified(false),
m_text_modified(false)
{
NodeMetadata::registerType(typeId(), typeName(), create, create);
}
virtual ~GenericNodeMetadata()
{
delete m_inventory;
}
NodeMetadata* clone(IGameDef *gamedef)
{
GenericNodeMetadata *d = new GenericNodeMetadata(m_gamedef);
d->m_inventory = new Inventory(*m_inventory);
d->m_text = m_text;
d->m_owner = m_owner;
d->m_infotext = m_infotext;
d->m_inventorydrawspec = m_inventorydrawspec;
d->m_allow_text_input = m_allow_text_input;
d->m_removal_disabled = m_removal_disabled;
d->m_enforce_owner = m_enforce_owner;
d->m_inventory_modified = m_inventory_modified;
d->m_text_modified = m_text_modified;
return d;
}
static NodeMetadata* create(IGameDef *gamedef)
{
GenericNodeMetadata *d = new GenericNodeMetadata(gamedef);
d->m_inventory = new Inventory(gamedef->idef());
return d;
}
static NodeMetadata* create(std::istream &is, IGameDef *gamedef)
{
GenericNodeMetadata *d = new GenericNodeMetadata(gamedef);
d->m_inventory = new Inventory(gamedef->idef());
d->m_inventory->deSerialize(is);
d->m_text = deSerializeLongString(is);
d->m_owner = deSerializeString(is);
d->m_infotext = deSerializeString(is);
d->m_inventorydrawspec = deSerializeString(is);
d->m_allow_text_input = readU8(is);
d->m_removal_disabled = readU8(is);
d->m_enforce_owner = readU8(is);
meta->setInfoText(deSerializeString(is));
meta->setInventoryDrawSpec(deSerializeString(is));
readU8(is); // m_allow_text_input
meta->setAllowRemoval(readU8(is) == 0);
readU8(is); // m_enforce_owner
int num_vars = readU32(is);
for(int i=0; i<num_vars; i++){
std::string name = deSerializeString(is);
std::string var = deSerializeLongString(is);
d->m_stringvars[name] = var;
meta->setString(name, var);
}
return d;
}
void serializeBody(std::ostream &os)
{
m_inventory->serialize(os);
os<<serializeLongString(m_text);
os<<serializeString(m_owner);
os<<serializeString(m_infotext);
os<<serializeString(m_inventorydrawspec);
writeU8(os, m_allow_text_input);
writeU8(os, m_removal_disabled);
writeU8(os, m_enforce_owner);
int num_vars = m_stringvars.size();
writeU32(os, num_vars);
for(std::map<std::string, std::string>::iterator
i = m_stringvars.begin(); i != m_stringvars.end(); i++){
os<<serializeString(i->first);
os<<serializeLongString(i->second);
}
}
std::string infoText()
{
return m_infotext;
}
Inventory* getInventory()
{
return m_inventory;
}
void inventoryModified()
{
m_inventory_modified = true;
}
bool step(float dtime)
{
return false;
}
bool nodeRemovalDisabled()
else if(id == NODEMETA_SIGN) // SignNodeMetadata
{
return m_removal_disabled;
meta->setString("text", deSerializeLongString(is));
meta->setInfoText("\"${text}\"");
meta->setFormSpec("field[text;;${text}]");
return false;
}
std::string getInventoryDrawSpecString()
else if(id == NODEMETA_CHEST) // ChestNodeMetadata
{
return m_inventorydrawspec;
meta->getInventory()->deSerialize(is);
meta->setInventoryDrawSpec("invsize[8,9;]"
"list[current_name;0;0,0;8,4;]"
"list[current_player;main;0,5;8,4;]");
return false;
}
bool allowsTextInput()
else if(id == NODEMETA_LOCKABLE_CHEST) // LockingChestNodeMetadata
{
return m_allow_text_input;
meta->setString("owner", deSerializeString(is));
meta->getInventory()->deSerialize(is);
meta->setInventoryDrawSpec("invsize[8,9;]"
"list[current_name;0;0,0;8,4;]"
"list[current_player;main;0,5;8,4;]");
return false;
}
std::string getText()
else if(id == NODEMETA_FURNACE) // FurnaceNodeMetadata
{
return m_text;
}
void setText(const std::string &t)
{
m_text = t;
m_text_modified = true;
}
std::string getOwner()
{
if(m_enforce_owner)
return m_owner;
else
return "";
}
void setOwner(std::string t)
{
m_owner = t;
}
/* Interface for GenericNodeMetadata */
meta->getInventory()->deSerialize(is);
int temp = 0;
is>>temp;
meta->setString("fuel_totaltime", ftos((float)temp/10));
temp = 0;
is>>temp;
meta->setString("fuel_time", ftos((float)temp/10));
temp = 0;
is>>temp;
//meta->setString("src_totaltime", ftos((float)temp/10));
temp = 0;
is>>temp;
meta->setString("src_time", ftos((float)temp/10));
void setInfoText(const std::string &text)
{
infostream<<"GenericNodeMetadata::setInfoText(\""
<<text<<"\")"<<std::endl;
m_infotext = text;
meta->setInventoryDrawSpec("invsize[8,9;]"
"list[current_name;fuel;2,3;1,1;]"
"list[current_name;src;2,1;1,1;]"
"list[current_name;dst;5,1;2,2;]"
"list[current_player;main;0,5;8,4;]");
return true;
}
void setInventoryDrawSpec(const std::string &text)
else
{
m_inventorydrawspec = text;
throw SerializationError("Unknown legacy node metadata");
}
void setAllowTextInput(bool b)
{
m_allow_text_input = b;
}
void setRemovalDisabled(bool b)
{
m_removal_disabled = b;
}
void setEnforceOwner(bool b)
{
m_enforce_owner = b;
}
bool isInventoryModified()
{
return m_inventory_modified;
}
void resetInventoryModified()
{
m_inventory_modified = false;
}
bool isTextModified()
{
return m_text_modified;
}
void resetTextModified()
{
m_text_modified = false;
}
void setString(const std::string &name, const std::string &var)
{
m_stringvars[name] = var;
}
std::string getString(const std::string &name)
{
std::map<std::string, std::string>::iterator i;
i = m_stringvars.find(name);
if(i == m_stringvars.end())
return "";
return i->second;
}
};
}
// Prototype
GenericNodeMetadata proto_GenericNodeMetadata(NULL);
static bool content_nodemeta_deserialize_legacy_meta(
std::istream &is, NodeMetadata *meta)
{
// Read id
s16 id = readS16(is);
// Read data
std::string data = deSerializeString(is);
std::istringstream tmp_is(data, std::ios::binary);
return content_nodemeta_deserialize_legacy_body(tmp_is, id, meta);
}
void content_nodemeta_deserialize_legacy(std::istream &is,
NodeMetadataList *meta, NodeTimerList *timers,
IGameDef *gamedef)
{
meta->clear();
timers->clear();
u16 version = readU16(is);
if(version > 1)
{
infostream<<__FUNCTION_NAME<<": version "<<version<<" not supported"
<<std::endl;
throw SerializationError(__FUNCTION_NAME);
}
u16 count = readU16(is);
for(u16 i=0; i<count; i++)
{
u16 p16 = readU16(is);
v3s16 p(0,0,0);
p.Z += p16 / MAP_BLOCKSIZE / MAP_BLOCKSIZE;
p16 -= p.Z * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
p.Y += p16 / MAP_BLOCKSIZE;
p16 -= p.Y * MAP_BLOCKSIZE;
p.X += p16;
if(meta->get(p) != NULL)
{
infostream<<"WARNING: "<<__FUNCTION_NAME<<": "
<<"already set data at position"
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<"): Ignoring."
<<std::endl;
continue;
}
NodeMetadata *data = new NodeMetadata(gamedef);
bool need_timer = content_nodemeta_deserialize_legacy_meta(is, data);
meta->set(p, data);
if(need_timer)
timers->set(p, NodeTimer(1., 0.));
}
}
void content_nodemeta_serialize_legacy(std::ostream &os, NodeMetadataList *meta)
{
// Sorry, I was too lazy to implement this. --kahrl
writeU16(os, 1); // version
writeU16(os, 0); // count
}
// END

@ -21,6 +21,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define CONTENT_NODEMETA_HEADER
#include "nodemetadata.h"
#include "nodetimer.h"
/*
Legacy nodemeta definitions
*/
void content_nodemeta_deserialize_legacy(std::istream &is,
NodeMetadataList *meta, NodeTimerList *timers,
IGameDef *gamedef);
void content_nodemeta_serialize_legacy(std::ostream &os, NodeMetadataList *meta);
#endif

@ -773,18 +773,11 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
// Activate stored objects
activateObjects(block);
// Run node metadata
bool changed = block->m_node_metadata->step((float)dtime_s);
if(changed)
{
MapEditEvent event;
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
event.p = block->getPos();
m_map->dispatchEvent(&event);
block->raiseModified(MOD_STATE_WRITE_NEEDED,
"node metadata modified in activateBlock");
}
// Run node timers
std::map<v3s16, f32> elapsed_timers =
block->m_node_timers.step((float)dtime_s);
if(!elapsed_timers.empty())
errorstream<<"Node timers don't work yet!"<<std::endl;
/* Handle ActiveBlockModifiers */
ABMHandler abmhandler(m_abms, dtime_s, this, false);
@ -1064,18 +1057,11 @@ void ServerEnvironment::step(float dtime)
block->raiseModified(MOD_STATE_WRITE_AT_UNLOAD,
"Timestamp older than 60s (step)");
// Run node metadata
bool changed = block->m_node_metadata->step(dtime);
if(changed)
{
MapEditEvent event;
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
event.p = p;
m_map->dispatchEvent(&event);
block->raiseModified(MOD_STATE_WRITE_NEEDED,
"node metadata modified in step");
}
// Run node timers
std::map<v3s16, f32> elapsed_timers =
block->m_node_timers.step(dtime);
if(!elapsed_timers.empty())
errorstream<<"Node timers don't work yet!"<<std::endl;
}
}

@ -2195,7 +2195,7 @@ void the_game(
ClientMap &map = client.getEnv().getClientMap();
NodeMetadata *meta = map.getNodeMetadata(nodepos);
if(meta){
infotext = narrow_to_wide(meta->infoText());
infotext = narrow_to_wide(meta->getInfoText());
} else {
MapNode n = map.getNode(nodepos);
if(nodedef->get(n).tname_tiles[0] == "unknown_block.png"){
@ -2321,6 +2321,8 @@ void the_game(
infostream<<"Ground right-clicked"<<std::endl;
// If metadata provides an inventory view, activate it
errorstream<<"Need to implement metadata formspecs"<<std::endl;
#if 0
if(meta && meta->getInventoryDrawSpecString() != "" && !random_input)
{
infostream<<"Launching custom inventory view"<<std::endl;
@ -2362,6 +2364,9 @@ void the_game(
&g_menumgr, dest,
wtext))->drop();
}
#else
if(0) /* do nothing */;
#endif
// Otherwise report right click to server
else
{

@ -1015,21 +1015,6 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
setNode(p, n);
/*
Add intial metadata
*/
std::string metadata_name = nodemgr->get(n).metadata_name;
if(metadata_name != ""){
NodeMetadata *meta = NodeMetadata::create(metadata_name, m_gamedef);
if(!meta){
errorstream<<"Failed to create node metadata \""
<<metadata_name<<"\""<<std::endl;
} else {
setNodeMetadata(p, meta);
}
}
/*
If node is under sunlight and doesn't let sunlight through,
take all sunlighted nodes under it and clear light from them
@ -1853,7 +1838,7 @@ NodeMetadata* Map::getNodeMetadata(v3s16 p)
<<std::endl;
return NULL;
}
NodeMetadata *meta = block->m_node_metadata->get(p_rel);
NodeMetadata *meta = block->m_node_metadata.get(p_rel);
return meta;
}
@ -1873,7 +1858,7 @@ void Map::setNodeMetadata(v3s16 p, NodeMetadata *meta)
<<std::endl;
return;
}
block->m_node_metadata->set(p_rel, meta);
block->m_node_metadata.set(p_rel, meta);
}
void Map::removeNodeMetadata(v3s16 p)
@ -1887,36 +1872,7 @@ void Map::removeNodeMetadata(v3s16 p)
<<std::endl;
return;
}
block->m_node_metadata->remove(p_rel);
}
void Map::nodeMetadataStep(float dtime,
core::map<v3s16, MapBlock*> &changed_blocks)
{
/*
NOTE:
Currently there is no way to ensure that all the necessary
blocks are loaded when this is run. (They might get unloaded)
NOTE: ^- Actually, that might not be so. In a quick test it
reloaded a block with a furnace when I walked back to it from
a distance.
*/
core::map<v2s16, MapSector*>::Iterator si;
si = m_sectors.getIterator();
for(; si.atEnd() == false; si++)
{
MapSector *sector = si.getNode()->getValue();
core::list< MapBlock * > sectorblocks;
sector->getBlocks(sectorblocks);
core::list< MapBlock * >::Iterator i;
for(i=sectorblocks.begin(); i!=sectorblocks.end(); i++)
{
MapBlock *block = *i;
bool changed = block->m_node_metadata->step(dtime);
if(changed)
changed_blocks[block->getPos()] = block;
}
}
block->m_node_metadata.remove(p_rel);
}
/*

@ -309,9 +309,7 @@ public:
NodeMetadata* getNodeMetadata(v3s16 p);
void setNodeMetadata(v3s16 p, NodeMetadata *meta);
void removeNodeMetadata(v3s16 p);
void nodeMetadataStep(float dtime,
core::map<v3s16, MapBlock*> &changed_blocks);
/*
Misc.
*/

@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "log.h"
#include "nameidmapping.h"
#include "content_mapnode.h" // For legacy name-id mapping
#include "content_nodemeta.h" // For legacy deserialization
#ifndef SERVER
#include "mapblock_mesh.h"
#endif
@ -39,7 +40,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
MapBlock::MapBlock(Map *parent, v3s16 pos, IGameDef *gamedef, bool dummy):
m_node_metadata(new NodeMetadataList),
m_parent(parent),
m_pos(pos),
m_gamedef(gamedef),
@ -79,8 +79,6 @@ MapBlock::~MapBlock()
}
#endif
delete m_node_metadata;
if(data)
delete[] data;
}
@ -605,7 +603,10 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
Node metadata
*/
std::ostringstream oss(std::ios_base::binary);
m_node_metadata->serialize(oss);
if(version >= 23)
m_node_metadata.serialize(oss);
else
content_nodemeta_serialize_legacy(oss, &m_node_metadata);
compressZlib(oss.str(), os);
/*
@ -613,6 +614,10 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
*/
if(disk)
{
// Node timers
if(version >= 23)
m_node_timers.serialize(os);
// Static objects
m_static_objects.serialize(os);
@ -665,12 +670,17 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
std::ostringstream oss(std::ios_base::binary);
decompressZlib(is, oss);
std::istringstream iss(oss.str(), std::ios_base::binary);
m_node_metadata->deSerialize(iss, m_gamedef);
if(version >= 23)
m_node_metadata.deSerialize(iss, m_gamedef);
else
content_nodemeta_deserialize_legacy(iss,
&m_node_metadata, &m_node_timers,
m_gamedef);
}
catch(SerializationError &e)
{
errorstream<<"WARNING: MapBlock::deSerialize(): Ignoring an error"
<<" while deserializing node metadata"<<std::endl;
<<" while deserializing node metadata: "<<e.what()<<std::endl;
}
/*
@ -678,6 +688,10 @@ void MapBlock::deSerialize(std::istream &is, u8 version, bool disk)
*/
if(disk)
{
// Node timers
if(version >= 23)
m_node_timers.deSerialize(is);
// Static objects
m_static_objects.deSerialize(is);
@ -857,7 +871,7 @@ void MapBlock::serialize_pre22(std::ostream &os, u8 version, bool disk)
{
try{
std::ostringstream oss(std::ios_base::binary);
m_node_metadata->serialize(oss);
content_nodemeta_serialize_legacy(oss, &m_node_metadata);
os<<serializeString(oss.str());
}
// This will happen if the string is longer than 65535
@ -870,7 +884,7 @@ void MapBlock::serialize_pre22(std::ostream &os, u8 version, bool disk)
else
{
std::ostringstream oss(std::ios_base::binary);
m_node_metadata->serialize(oss);
content_nodemeta_serialize_legacy(oss, &m_node_metadata);
compressZlib(oss.str(), os);
//os<<serializeLongString(oss.str());
}
@ -1024,7 +1038,9 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk)
{
std::string data = deSerializeString(is);
std::istringstream iss(data, std::ios_base::binary);
m_node_metadata->deSerialize(iss, m_gamedef);
content_nodemeta_deserialize_legacy(iss,
&m_node_metadata, &m_node_timers,
m_gamedef);
}
else
{
@ -1032,7 +1048,9 @@ void MapBlock::deSerialize_pre22(std::istream &is, u8 version, bool disk)
std::ostringstream oss(std::ios_base::binary);
decompressZlib(is, oss);
std::istringstream iss(oss.str(), std::ios_base::binary);
m_node_metadata->deSerialize(iss, m_gamedef);
content_nodemeta_deserialize_legacy(iss,
&m_node_metadata, &m_node_timers,
m_gamedef);
}
}
catch(SerializationError &e)

@ -31,6 +31,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "constants.h"
#include "voxel.h"
#include "staticobject.h"
#include "nodemetadata.h"
#include "nodetimer.h"
#include "modifiedstate.h"
class Map;
@ -473,7 +475,8 @@ public:
//JMutex mesh_mutex;
#endif
NodeMetadataList *m_node_metadata;
NodeMetadataList m_node_metadata;
NodeTimerList m_node_timers;
StaticObjectList m_static_objects;
private:

@ -145,7 +145,6 @@ void ContentFeatures::reset()
diggable = true;
climbable = false;
buildable_to = false;
metadata_name = "";
liquid_type = LIQUID_NONE;
liquid_alternative_flowing = "";
liquid_alternative_source = "";
@ -194,7 +193,7 @@ void ContentFeatures::serialize(std::ostream &os)
writeU8(os, diggable);
writeU8(os, climbable);
writeU8(os, buildable_to);
os<<serializeString(metadata_name);
os<<serializeString(""); // legacy: used to be metadata_name
writeU8(os, liquid_type);
os<<serializeString(liquid_alternative_flowing);
os<<serializeString(liquid_alternative_source);
@ -248,7 +247,7 @@ void ContentFeatures::deSerialize(std::istream &is)
diggable = readU8(is);
climbable = readU8(is);
buildable_to = readU8(is);
metadata_name = deSerializeString(is);
deSerializeString(is); // legacy: used to be metadata_name
liquid_type = (enum LiquidType)readU8(is);
liquid_alternative_flowing = deSerializeString(is);
liquid_alternative_source = deSerializeString(is);

@ -179,8 +179,6 @@ struct ContentFeatures
bool climbable;
// Player can build on these
bool buildable_to;
// Metadata name of node (eg. "furnace")
std::string metadata_name;
// Whether the node is non-liquid, source liquid or flowing liquid
enum LiquidType liquid_type;
// If the content is liquid, this is the flowing version of the liquid.

@ -19,11 +19,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "nodemetadata.h"
#include "utility.h"
#include "mapnode.h"
#include "exceptions.h"
#include "gamedef.h"
#include "inventory.h"
#include <sstream>
#include "content_mapnode.h"
#include "log.h"
/*
@ -31,161 +30,120 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
NodeMetadata::NodeMetadata(IGameDef *gamedef):
m_gamedef(gamedef)
m_stringvars(),
m_inventory(new Inventory(gamedef->idef())),
m_inventorydrawspec(""),
m_formspec(""),
m_infotext(""),
m_allow_removal(true)
{
}
NodeMetadata::~NodeMetadata()
{
delete m_inventory;
}
NodeMetadata* NodeMetadata::create(const std::string &name, IGameDef *gamedef)
void NodeMetadata::serialize(std::ostream &os) const
{
// Find factory function
core::map<std::string, Factory2>::Node *n;
n = m_names.find(name);
if(n == NULL)
{
// If factory is not found, just return.
errorstream<<"WARNING: NodeMetadata: No factory for name=\""
<<name<<"\""<<std::endl;
return NULL;
}
// Try to load the metadata. If it fails, just return.
try
{
Factory2 f2 = n->getValue();
NodeMetadata *meta = (*f2)(gamedef);
return meta;
}
catch(SerializationError &e)
{
errorstream<<"NodeMetadata: SerializationError "
<<"while creating name=\""<<name<<"\""<<std::endl;
return NULL;
int num_vars = m_stringvars.size();
writeU32(os, num_vars);
for(std::map<std::string, std::string>::const_iterator
i = m_stringvars.begin(); i != m_stringvars.end(); i++){
os<<serializeString(i->first);
os<<serializeLongString(i->second);
}
m_inventory->serialize(os);
os<<serializeString(m_inventorydrawspec);
os<<serializeString(m_formspec);
os<<serializeString(m_infotext);
writeU8(os, m_allow_removal);
}
NodeMetadata* NodeMetadata::deSerialize(std::istream &is, IGameDef *gamedef)
void NodeMetadata::deSerialize(std::istream &is)
{
// Read id
u8 buf[2];
is.read((char*)buf, 2);
s16 id = readS16(buf);
// Read data
std::string data = deSerializeString(is);
// Find factory function
core::map<u16, Factory>::Node *n;
n = m_types.find(id);
if(n == NULL)
{
// If factory is not found, just return.
infostream<<"WARNING: NodeMetadata: No factory for typeId="
<<id<<std::endl;
return NULL;
}
// Try to load the metadata. If it fails, just return.
try
{
std::istringstream iss(data, std::ios_base::binary);
Factory f = n->getValue();
NodeMetadata *meta = (*f)(iss, gamedef);
return meta;
}
catch(SerializationError &e)
{
infostream<<"WARNING: NodeMetadata: ignoring SerializationError"<<std::endl;
return NULL;
m_stringvars.clear();
int num_vars = readU32(is);
for(int i=0; i<num_vars; i++){
std::string name = deSerializeString(is);
std::string var = deSerializeLongString(is);
m_stringvars[name] = var;
}
m_inventory->deSerialize(is);
m_inventorydrawspec = deSerializeString(is);
m_formspec = deSerializeString(is);
m_infotext = deSerializeString(is);
m_allow_removal = readU8(is);
}
void NodeMetadata::serialize(std::ostream &os)
void NodeMetadata::clear()
{
u8 buf[2];
writeU16(buf, typeId());
os.write((char*)buf, 2);
std::ostringstream oss(std::ios_base::binary);
serializeBody(oss);
os<<serializeString(oss.str());
}
void NodeMetadata::registerType(u16 id, const std::string &name, Factory f,
Factory2 f2)
{
{ // typeId
core::map<u16, Factory>::Node *n;
n = m_types.find(id);
if(!n)
m_types.insert(id, f);
}
{ // typeName
core::map<std::string, Factory2>::Node *n;
n = m_names.find(name);
if(!n)
m_names.insert(name, f2);
}
m_stringvars.clear();
m_inventory->clear();
m_inventorydrawspec = "";
m_formspec = "";
m_infotext = "";
m_allow_removal = true;
}
/*
NodeMetadataList
*/
void NodeMetadataList::serialize(std::ostream &os)
void NodeMetadataList::serialize(std::ostream &os) const
{
u8 buf[6];
u16 version = 1;
writeU16(buf, version);
os.write((char*)buf, 2);
/*
Version 0 is a placeholder for "nothing to see here; go away."
*/
if(m_data.size() == 0){
writeU8(os, 0); // version
return;
}
writeU8(os, 1); // version
u16 count = m_data.size();
writeU16(buf, count);
os.write((char*)buf, 2);
writeU16(os, count);
for(core::map<v3s16, NodeMetadata*>::Iterator
i = m_data.getIterator();
i.atEnd()==false; i++)
for(std::map<v3s16, NodeMetadata*>::const_iterator
i = m_data.begin();
i != m_data.end(); i++)
{
v3s16 p = i.getNode()->getKey();
NodeMetadata *data = i.getNode()->getValue();
v3s16 p = i->first;
NodeMetadata *data = i->second;
u16 p16 = p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X;
writeU16(buf, p16);
os.write((char*)buf, 2);
writeU16(os, p16);
data->serialize(os);
}
}
void NodeMetadataList::deSerialize(std::istream &is, IGameDef *gamedef)
{
m_data.clear();
u8 buf[6];
u8 version = readU8(is);
is.read((char*)buf, 2);
u16 version = readU16(buf);
if(version == 0){
// Nothing
return;
}
if(version > 1)
{
if(version != 1){
infostream<<__FUNCTION_NAME<<": version "<<version<<" not supported"
<<std::endl;
throw SerializationError("NodeMetadataList::deSerialize");
}
is.read((char*)buf, 2);
u16 count = readU16(buf);
u16 count = readU16(is);
for(u16 i=0; i<count; i++)
{
is.read((char*)buf, 2);
u16 p16 = readU16(buf);
u16 p16 = readU16(is);
v3s16 p(0,0,0);
p.Z += p16 / MAP_BLOCKSIZE / MAP_BLOCKSIZE;
@ -193,43 +151,33 @@ void NodeMetadataList::deSerialize(std::istream &is, IGameDef *gamedef)
p.Y += p16 / MAP_BLOCKSIZE;
p16 -= p.Y * MAP_BLOCKSIZE;
p.X += p16;
NodeMetadata *data = NodeMetadata::deSerialize(is, gamedef);
if(data == NULL)
continue;
if(m_data.find(p))
if(m_data.find(p) != m_data.end())
{
infostream<<"WARNING: NodeMetadataList::deSerialize(): "
<<"already set data at position"
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<"): Ignoring."
<<std::endl;
delete data;
continue;
}
m_data.insert(p, data);
NodeMetadata *data = new NodeMetadata(gamedef);
data->deSerialize(is);
m_data[p] = data;
}
}
NodeMetadataList::~NodeMetadataList()
{
for(core::map<v3s16, NodeMetadata*>::Iterator
i = m_data.getIterator();
i.atEnd()==false; i++)
{
delete i.getNode()->getValue();
}
clear();
}
NodeMetadata* NodeMetadataList::get(v3s16 p)
{
core::map<v3s16, NodeMetadata*>::Node *n;
n = m_data.find(p);
if(n == NULL)
std::map<v3s16, NodeMetadata*>::const_iterator n = m_data.find(p);
if(n == m_data.end())
return NULL;
return n->getValue();
return n->second;
}
void NodeMetadataList::remove(v3s16 p)
@ -238,29 +186,23 @@ void NodeMetadataList::remove(v3s16 p)
if(olddata)
{
delete olddata;
m_data.remove(p);
m_data.erase(p);
}
}
void NodeMetadataList::set(v3s16 p, NodeMetadata *d)
{
remove(p);
m_data.insert(p, d);
m_data.insert(std::make_pair(p, d));
}
bool NodeMetadataList::step(float dtime)
void NodeMetadataList::clear()
{
bool something_changed = false;
for(core::map<v3s16, NodeMetadata*>::Iterator
i = m_data.getIterator();
i.atEnd()==false; i++)
for(std::map<v3s16, NodeMetadata*>::iterator
i = m_data.begin();
i != m_data.end(); i++)
{
v3s16 p = i.getNode()->getKey();
NodeMetadata *meta = i.getNode()->getValue();
bool changed = meta->step(dtime);
if(changed)
something_changed = true;
delete i->second;
}
return something_changed;
m_data.clear();
}

@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes.h"
#include <string>
#include <iostream>
#include <map>
/*
NodeMetadata stores arbitary amounts of data for special blocks.
@ -39,77 +40,89 @@ class IGameDef;
class NodeMetadata
{
public:
typedef NodeMetadata* (*Factory)(std::istream&, IGameDef *gamedef);
typedef NodeMetadata* (*Factory2)(IGameDef *gamedef);
NodeMetadata(IGameDef *gamedef);
virtual ~NodeMetadata();
~NodeMetadata();
static NodeMetadata* create(const std::string &name, IGameDef *gamedef);
static NodeMetadata* deSerialize(std::istream &is, IGameDef *gamedef);
void serialize(std::ostream &os);
void serialize(std::ostream &os) const;
void deSerialize(std::istream &is);
virtual u16 typeId() const = 0;
virtual const char* typeName() const = 0;
virtual NodeMetadata* clone(IGameDef *gamedef) = 0;
virtual void serializeBody(std::ostream &os) = 0;
void clear();
// Called on client-side; shown on screen when pointed at
virtual std::string infoText() {return "";}
// Generic key/value store
std::string getString(const std::string &name) const
{
std::map<std::string, std::string>::const_iterator i;
i = m_stringvars.find(name);
if(i == m_stringvars.end())
return "";
return i->second;
}
void setString(const std::string &name, const std::string &var)
{
if(var.empty())
m_stringvars.erase(name);
else
m_stringvars[name] = var;
}
// The inventory
Inventory* getInventory()
{
return m_inventory;
}
//
virtual Inventory* getInventory() {return NULL;}
// Called always after the inventory is modified, before the changes
// are copied elsewhere
virtual void inventoryModified(){}
// A step in time. Shall return true if metadata changed.
virtual bool step(float dtime) {return false;}
// Whether the related node and this metadata cannot be removed
virtual bool nodeRemovalDisabled(){return false;}
// If non-empty, player can interact by using an inventory view
// See format in guiInventoryMenu.cpp.
virtual std::string getInventoryDrawSpecString(){return "";}
std::string getInventoryDrawSpec() const
{
return m_inventorydrawspec;
}
void setInventoryDrawSpec(const std::string &text)
{
m_inventorydrawspec = text;
}
// If non-empty, player can interact by using an form view
// See format in guiFormMenu.cpp.
std::string getFormSpec() const
{
return m_formspec;
}
void setFormSpec(const std::string &text)
{
m_formspec = text;
}
// Called on client-side; shown on screen when pointed at
std::string getInfoText() const
{
return m_infotext;
}
void setInfoText(const std::string &text)
{
m_infotext = text;
}
// Whether the related node and this metadata can be removed
bool getAllowRemoval() const
{
return m_allow_removal;
}
void setAllowRemoval(bool b)
{
m_allow_removal = b;
}
// If true, player can interact by writing text
virtual bool allowsTextInput(){ return false; }
// Get old text for player interaction
virtual std::string getText(){ return ""; }
// Set player-written text
virtual void setText(const std::string &t){}
// If returns non-empty, only given player can modify text/inventory
virtual std::string getOwner(){ return std::string(""); }
// The name of the player who placed the node
virtual void setOwner(std::string t){}
/* Interface for GenericNodeMetadata */
virtual void setInfoText(const std::string &text){};
virtual void setInventoryDrawSpec(const std::string &text){};
virtual void setAllowTextInput(bool b){};
virtual void setRemovalDisabled(bool b){};
virtual void setEnforceOwner(bool b){};
virtual bool isInventoryModified(){return false;};
virtual void resetInventoryModified(){};
virtual bool isTextModified(){return false;};
virtual void resetTextModified(){};
virtual void setString(const std::string &name, const std::string &var){}
virtual std::string getString(const std::string &name){return "";}
protected:
static void registerType(u16 id, const std::string &name, Factory f,
Factory2 f2);
IGameDef *m_gamedef;
private:
static core::map<u16, Factory> m_types;
static core::map<std::string, Factory2> m_names;
std::map<std::string, std::string> m_stringvars;
Inventory *m_inventory;
std::string m_inventorydrawspec;
std::string m_formspec;
std::string m_infotext;
bool m_allow_removal;
};
/*
List of metadata of all the nodes of a block
*/
@ -119,7 +132,7 @@ class NodeMetadataList
public:
~NodeMetadataList();
void serialize(std::ostream &os);
void serialize(std::ostream &os) const;
void deSerialize(std::istream &is, IGameDef *gamedef);
// Get pointer to data
@ -128,12 +141,11 @@ public:
void remove(v3s16 p);
// Deletes old data and sets a new one
void set(v3s16 p, NodeMetadata *d);
// Deletes all
void clear();
// A step in time. Returns true if something changed.
bool step(float dtime);
private:
core::map<v3s16, NodeMetadata*> m_data;
std::map<v3s16, NodeMetadata*> m_data;
};
#endif

141
src/nodetimer.cpp Normal file

@ -0,0 +1,141 @@
/*
Minetest-c55
Copyright (C) 2010-2012 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 "nodetimer.h"
#include "utility.h"
#include "log.h"
/*
NodeTimer
*/
void NodeTimer::serialize(std::ostream &os) const
{
writeF1000(os, duration);
writeF1000(os, elapsed);
}
void NodeTimer::deSerialize(std::istream &is)
{
duration = readF1000(is);
elapsed = readF1000(is);
}
/*
NodeTimerList
*/
void NodeTimerList::serialize(std::ostream &os) const
{
/*
Version 0 is a placeholder for "nothing to see here; go away."
*/
if(m_data.size() == 0){
writeU8(os, 0); // version
return;
}
writeU8(os, 1); // version
writeU16(os, m_data.size());
for(std::map<v3s16, NodeTimer>::const_iterator
i = m_data.begin();
i != m_data.end(); i++){
v3s16 p = i->first;
NodeTimer t = i->second;
u16 p16 = p.Z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + p.Y*MAP_BLOCKSIZE + p.X;
writeU16(os, p16);
t.serialize(os);
}
}
void NodeTimerList::deSerialize(std::istream &is)
{
m_data.clear();
u8 version = readU8(is);
if(version == 0)
return;
if(version != 1)
throw SerializationError("unsupported NodeTimerList version");
u16 count = readU16(is);
for(u16 i=0; i<count; i++)
{
u16 p16 = readU16(is);
v3s16 p(0,0,0);
p.Z += p16 / MAP_BLOCKSIZE / MAP_BLOCKSIZE;
p16 -= p.Z * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
p.Y += p16 / MAP_BLOCKSIZE;
p16 -= p.Y * MAP_BLOCKSIZE;
p.X += p16;
NodeTimer t;
t.deSerialize(is);
if(t.duration <= 0)
{
infostream<<"WARNING: NodeTimerList::deSerialize(): "
<<"invalid data at position"
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<"): Ignoring."
<<std::endl;
continue;
}
if(m_data.find(p) != m_data.end())
{
infostream<<"WARNING: NodeTimerList::deSerialize(): "
<<"already set data at position"
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<"): Ignoring."
<<std::endl;
continue;
}
m_data.insert(std::make_pair(p, t));
}
}
std::map<v3s16, f32> NodeTimerList::step(float dtime)
{
std::map<v3s16, f32> elapsed_timers;
// Increment timers
for(std::map<v3s16, NodeTimer>::iterator
i = m_data.begin();
i != m_data.end(); i++){
v3s16 p = i->first;
NodeTimer t = i->second;
t.elapsed += dtime;
if(t.elapsed >= t.duration)
elapsed_timers.insert(std::make_pair(p, t.elapsed));
else
i->second = t;
}
// Delete elapsed timers
for(std::map<v3s16, f32>::const_iterator
i = elapsed_timers.begin();
i != elapsed_timers.end(); i++){
v3s16 p = i->first;
m_data.erase(p);
}
return elapsed_timers;
}

91
src/nodetimer.h Normal file

@ -0,0 +1,91 @@
/*
Minetest-c55
Copyright (C) 2010-2012 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 NODETIMER_HEADER
#define NODETIMER_HEADER
#include "irrlichttypes.h"
#include <iostream>
#include <map>
/*
NodeTimer provides per-node timed callback functionality.
Can be used for:
- Furnaces, to keep the fire burnin'
- "activated" nodes that snap back to their original state
after a fixed amount of time (mesecons buttons, for example)
*/
class NodeTimer
{
public:
NodeTimer(): duration(0.), elapsed(0.) {}
NodeTimer(f32 duration_, f32 elapsed_):
duration(duration_), elapsed(elapsed_) {}
~NodeTimer() {}
void serialize(std::ostream &os) const;
void deSerialize(std::istream &is);
f32 duration;
f32 elapsed;
};
/*
List of timers of all the nodes of a block
*/
class NodeTimerList
{
public:
NodeTimerList() {}
~NodeTimerList() {}
void serialize(std::ostream &os) const;
void deSerialize(std::istream &is);
// Get timer
NodeTimer get(v3s16 p){
std::map<v3s16, NodeTimer>::iterator n = m_data.find(p);
if(n == m_data.end())
return NodeTimer();
return n->second;
}
// Deletes timer
void remove(v3s16 p){
m_data.erase(p);
}
// Deletes old timer and sets a new one
void set(v3s16 p, NodeTimer t){
m_data[p] = t;
}
// Deletes all timers
void clear(){
m_data.clear();
}
// A step in time. Returns map of elapsed timers.
std::map<v3s16, f32> step(float dtime);
private:
std::map<v3s16, NodeTimer> m_data;
};
#endif

@ -1080,6 +1080,8 @@ static ContentFeatures read_content_features(lua_State *L, int index)
"deprecated: use 'drop' field");
warn_if_field_exists(L, index, "extra_dug_item_rarity",
"deprecated: use 'drop' field");
warn_if_field_exists(L, index, "metadata_name",
"deprecated: use on_add and metadata callbacks");
// True for all ground-like things like stone and mud, false for eg. trees
getboolfield(L, index, "is_ground_content", f.is_ground_content);
@ -1096,8 +1098,6 @@ static ContentFeatures read_content_features(lua_State *L, int index)
getboolfield(L, index, "climbable", f.climbable);
// Player can build on these
getboolfield(L, index, "buildable_to", f.buildable_to);
// Metadata name of node (eg. "furnace")
getstringfield(L, index, "metadata_name", f.metadata_name);
// Whether the node is non-liquid, source liquid or flowing liquid
f.liquid_type = (LiquidType)getenumfield(L, index, "liquidtype",
es_LiquidType, LIQUID_NONE);
@ -1947,22 +1947,17 @@ private:
return *(NodeMetaRef**)ud; // unbox pointer
}
static NodeMetadata* getmeta(NodeMetaRef *ref)
static NodeMetadata* getmeta(NodeMetaRef *ref, bool auto_create)
{
NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p);
if(meta == NULL && auto_create)
{
meta = new NodeMetadata(ref->m_env->getGameDef());
ref->m_env->getMap().setNodeMetadata(ref->m_p, meta);
}
return meta;
}
/*static IGenericNodeMetadata* getgenericmeta(NodeMetaRef *ref)
{
NodeMetadata *meta = getmeta(ref);
if(meta == NULL)
return NULL;
if(meta->typeId() != NODEMETA_GENERIC)
return NULL;
return (IGenericNodeMetadata*)meta;
}*/
static void reportMetadataChange(NodeMetaRef *ref)
{
// Inform other things that the metadata has changed
@ -1987,106 +1982,99 @@ private:
return 0;
}
// get_type(self)
static int l_get_type(lua_State *L)
// get_string(self, name)
static int l_get_string(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
std::string name = luaL_checkstring(L, 2);
NodeMetadata *meta = getmeta(ref, false);
if(meta == NULL){
lua_pushnil(L);
lua_pushlstring(L, "", 0);
return 1;
}
// Do it
lua_pushstring(L, meta->typeName());
std::string str = meta->getString(name);
lua_pushlstring(L, str.c_str(), str.size());
return 1;
}
// allows_text_input(self)
static int l_allows_text_input(lua_State *L)
// set_string(self, name, var)
static int l_set_string(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
lua_pushboolean(L, meta->allowsTextInput());
return 1;
}
std::string name = luaL_checkstring(L, 2);
size_t len = 0;
const char *s = lua_tolstring(L, 3, &len);
std::string str(s, len);
// set_text(self, text)
static int l_set_text(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
std::string text = luaL_checkstring(L, 2);
meta->setText(text);
NodeMetadata *meta = getmeta(ref, !str.empty());
if(meta == NULL || str == meta->getString(name))
return 0;
meta->setString(name, str);
reportMetadataChange(ref);
return 0;
}
// get_text(self)
static int l_get_text(lua_State *L)
// get_int(self, name)
static int l_get_int(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
std::string text = meta->getText();
lua_pushstring(L, text.c_str());
return 1;
}
std::string name = lua_tostring(L, 2);
// get_owner(self)
static int l_get_owner(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
std::string owner = meta->getOwner();
lua_pushstring(L, owner.c_str());
return 1;
}
// set_owner(self, string)
static int l_set_owner(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
std::string owner = luaL_checkstring(L, 2);
meta->setOwner(owner);
reportMetadataChange(ref);
return 1;
}
// get_allow_removal(self)
static int l_get_allow_removal(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
NodeMetadata *meta = getmeta(ref, false);
if(meta == NULL){
lua_pushboolean(L, true);
lua_pushnumber(L, 0);
return 1;
}
// Do it
lua_pushboolean(L, !meta->nodeRemovalDisabled());
std::string str = meta->getString(name);
lua_pushnumber(L, stoi(str));
return 1;
}
/* IGenericNodeMetadata interface */
// set_infotext(self, text)
static int l_set_infotext(lua_State *L)
// set_int(self, name, var)
static int l_set_int(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
std::string text = luaL_checkstring(L, 2);
meta->setInfoText(text);
std::string name = lua_tostring(L, 2);
int a = lua_tointeger(L, 3);
std::string str = itos(a);
NodeMetadata *meta = getmeta(ref, true);
if(meta == NULL || str == meta->getString(name))
return 0;
meta->setString(name, str);
reportMetadataChange(ref);
return 0;
}
// get_float(self, name)
static int l_get_float(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
std::string name = lua_tostring(L, 2);
NodeMetadata *meta = getmeta(ref, false);
if(meta == NULL){
lua_pushnumber(L, 0);
return 1;
}
std::string str = meta->getString(name);
lua_pushnumber(L, stof(str));
return 1;
}
// set_float(self, name, var)
static int l_set_float(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
std::string name = lua_tostring(L, 2);
float a = lua_tonumber(L, 3);
std::string str = ftos(a);
NodeMetadata *meta = getmeta(ref, true);
if(meta == NULL || str == meta->getString(name))
return 0;
meta->setString(name, str);
reportMetadataChange(ref);
return 0;
}
@ -2095,140 +2083,132 @@ private:
static int l_get_inventory(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
getmeta(ref, true); // try to ensure the metadata exists
InvRef::createNodeMeta(L, ref->m_p);
return 1;
}
// get_inventory_draw_spec(self)
static int l_get_inventory_draw_spec(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref, false);
if(meta == NULL){
lua_pushlstring(L, "", 0);
return 1;
}
std::string str = meta->getInventoryDrawSpec();
lua_pushlstring(L, str.c_str(), str.size());
return 1;
}
// set_inventory_draw_spec(self, text)
static int l_set_inventory_draw_spec(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
std::string text = luaL_checkstring(L, 2);
meta->setInventoryDrawSpec(text);
size_t len = 0;
const char *s = lua_tolstring(L, 2, &len);
std::string str(s, len);
NodeMetadata *meta = getmeta(ref, !str.empty());
if(meta == NULL || str == meta->getInventoryDrawSpec())
return 0;
meta->setInventoryDrawSpec(str);
reportMetadataChange(ref);
return 0;
}
// set_allow_text_input(self, text)
static int l_set_allow_text_input(lua_State *L)
// get_form_spec(self)
static int l_get_form_spec(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
bool b = lua_toboolean(L, 2);
meta->setAllowTextInput(b);
NodeMetadata *meta = getmeta(ref, false);
if(meta == NULL){
lua_pushlstring(L, "", 0);
return 1;
}
std::string str = meta->getFormSpec();
lua_pushlstring(L, str.c_str(), str.size());
return 1;
}
// set_form_spec(self, text)
static int l_set_form_spec(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
size_t len = 0;
const char *s = lua_tolstring(L, 2, &len);
std::string str(s, len);
NodeMetadata *meta = getmeta(ref, !str.empty());
if(meta == NULL || str == meta->getFormSpec())
return 0;
meta->setFormSpec(str);
reportMetadataChange(ref);
return 0;
}
// set_allow_removal(self, text)
// get_infotext(self)
static int l_get_infotext(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref, false);
if(meta == NULL){
lua_pushlstring(L, "", 0);
return 1;
}
std::string str = meta->getInfoText();
lua_pushlstring(L, str.c_str(), str.size());
return 1;
}
// set_infotext(self, text)
static int l_set_infotext(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
size_t len = 0;
const char *s = lua_tolstring(L, 2, &len);
std::string str(s, len);
NodeMetadata *meta = getmeta(ref, !str.empty());
if(meta == NULL || str == meta->getInfoText())
return 0;
meta->setInfoText(str);
reportMetadataChange(ref);
return 0;
}
// get_allow_removal(self)
static int l_get_allow_removal(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref, false);
if(meta == NULL){
lua_pushboolean(L, true);
return 1;
}
lua_pushboolean(L, meta->getAllowRemoval());
return 1;
}
// set_allow_removal(self, flag)
static int l_set_allow_removal(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
bool b = lua_toboolean(L, 2);
meta->setRemovalDisabled(!b);
bool flag = lua_toboolean(L, 2);
NodeMetadata *meta = getmeta(ref, flag != true);
if(meta == NULL || flag == meta->getAllowRemoval())
return 0;
meta->setAllowRemoval(flag);
reportMetadataChange(ref);
return 0;
}
// set_enforce_owner(self, text)
static int l_set_enforce_owner(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
bool b = lua_toboolean(L, 2);
meta->setEnforceOwner(b);
reportMetadataChange(ref);
return 0;
}
// is_inventory_modified(self)
static int l_is_inventory_modified(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
lua_pushboolean(L, meta->isInventoryModified());
return 1;
}
// reset_inventory_modified(self)
static int l_reset_inventory_modified(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
meta->resetInventoryModified();
reportMetadataChange(ref);
return 0;
}
// is_text_modified(self)
static int l_is_text_modified(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
lua_pushboolean(L, meta->isTextModified());
return 1;
}
// reset_text_modified(self)
static int l_reset_text_modified(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
meta->resetTextModified();
reportMetadataChange(ref);
return 0;
}
// set_string(self, name, var)
static int l_set_string(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
std::string name = luaL_checkstring(L, 2);
size_t len = 0;
const char *s = lua_tolstring(L, 3, &len);
std::string str(s, len);
meta->setString(name, str);
reportMetadataChange(ref);
return 0;
}
// get_string(self, name)
static int l_get_string(lua_State *L)
{
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref);
if(meta == NULL) return 0;
// Do it
std::string name = luaL_checkstring(L, 2);
std::string str = meta->getString(name);
lua_pushlstring(L, str.c_str(), str.size());
return 1;
}
public:
NodeMetaRef(v3s16 p, ServerEnvironment *env):
m_p(p),
@ -2281,25 +2261,21 @@ public:
};
const char NodeMetaRef::className[] = "NodeMetaRef";
const luaL_reg NodeMetaRef::methods[] = {
method(NodeMetaRef, get_type),
method(NodeMetaRef, allows_text_input),
method(NodeMetaRef, set_text),
method(NodeMetaRef, get_text),
method(NodeMetaRef, get_owner),
method(NodeMetaRef, set_owner),
method(NodeMetaRef, get_allow_removal),
method(NodeMetaRef, set_infotext),
method(NodeMetaRef, get_inventory),
method(NodeMetaRef, set_inventory_draw_spec),
method(NodeMetaRef, set_allow_text_input),
method(NodeMetaRef, set_allow_removal),
method(NodeMetaRef, set_enforce_owner),
method(NodeMetaRef, is_inventory_modified),
method(NodeMetaRef, reset_inventory_modified),
method(NodeMetaRef, is_text_modified),
method(NodeMetaRef, reset_text_modified),
method(NodeMetaRef, set_string),
method(NodeMetaRef, get_string),
method(NodeMetaRef, set_string),
method(NodeMetaRef, get_int),
method(NodeMetaRef, set_int),
method(NodeMetaRef, get_float),
method(NodeMetaRef, set_float),
method(NodeMetaRef, get_inventory),
method(NodeMetaRef, get_inventory_draw_spec),
method(NodeMetaRef, set_inventory_draw_spec),
method(NodeMetaRef, get_form_spec),
method(NodeMetaRef, set_form_spec),
method(NodeMetaRef, get_infotext),
method(NodeMetaRef, set_infotext),
method(NodeMetaRef, get_allow_removal),
method(NodeMetaRef, set_allow_removal),
{0,0}
};

@ -57,12 +57,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
19: new content type handling
20: many existing content types translated to extended ones
21: dynamic content type allocation
22: full 16-bit content types, minerals removed, facedir & wallmounted changed
22: minerals removed, facedir & wallmounted changed
23: NodeTimers, new node metadata format
*/
// This represents an uninitialized or invalid format
#define SER_FMT_VER_INVALID 255
// Highest supported serialization version
#define SER_FMT_VER_HIGHEST 22
#define SER_FMT_VER_HIGHEST 23
// Lowest supported serialization version
#define SER_FMT_VER_LOWEST 0

@ -2417,47 +2417,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}
else if(command == TOSERVER_SIGNNODETEXT)
{
if(!checkPriv(player->getName(), "interact"))
return;
/*
u16 command
v3s16 p
u16 textlen
textdata
*/
std::string datastring((char*)&data[2], datasize-2);
std::istringstream is(datastring, std::ios_base::binary);
u8 buf[6];
// Read stuff
is.read((char*)buf, 6);
v3s16 p = readV3S16(buf);
is.read((char*)buf, 2);
u16 textlen = readU16(buf);
std::string text;
for(u16 i=0; i<textlen; i++)
{
is.read((char*)buf, 1);
text += (char)buf[0];
}
NodeMetadata *meta = m_env->getMap().getNodeMetadata(p);
if(!meta)
return;
meta->setText(text);
actionstream<<player->getName()<<" writes \""<<text<<"\" to sign"
<<" at "<<PP(p)<<std::endl;
v3s16 blockpos = getNodeBlockPos(p);
MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
if(block)
{
block->raiseModified(MOD_STATE_WRITE_NEEDED,
"sign node text");
}
setBlockNotSent(blockpos);
infostream<<"Server: SIGNNODETEXT not supported anymore"
<<std::endl;
return;
}
else if(command == TOSERVER_INVENTORY_ACTION)
{
@ -2540,7 +2502,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}
// If player is not an admin, check for ownership of src and dst
if(!checkPriv(player->getName(), "server"))
/*if(!checkPriv(player->getName(), "server"))
{
std::string owner_from = getInventoryOwner(ma->from_inv);
if(owner_from != "" && owner_from != player->getName())
@ -2561,7 +2523,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
delete a;
return;
}
}
}*/
}
/*
Handle restrictions and special cases of the drop action
@ -2581,7 +2543,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
return;
}
// If player is not an admin, check for ownership
else if(!checkPriv(player->getName(), "server"))
/*else if(!checkPriv(player->getName(), "server"))
{
std::string owner_from = getInventoryOwner(da->from_inv);
if(owner_from != "" && owner_from != player->getName())
@ -2592,7 +2554,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
delete a;
return;
}
}
}*/
}
/*
Handle restrictions and special cases of the craft action
@ -2619,7 +2581,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}
// If player is not an admin, check for ownership of inventory
if(!checkPriv(player->getName(), "server"))
/*if(!checkPriv(player->getName(), "server"))
{
std::string owner_craft = getInventoryOwner(ca->craft_inv);
if(owner_craft != "" && owner_craft != player->getName())
@ -2630,7 +2592,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
delete a;
return;
}
}
}*/
}
// Do the action
@ -3223,33 +3185,6 @@ Inventory* Server::getInventory(const InventoryLocation &loc)
}
return NULL;
}
std::string Server::getInventoryOwner(const InventoryLocation &loc)
{
switch(loc.type){
case InventoryLocation::UNDEFINED:
{}
break;
case InventoryLocation::CURRENT_PLAYER:
{}
break;
case InventoryLocation::PLAYER:
{
return loc.name;
}
break;
case InventoryLocation::NODEMETA:
{
NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
if(!meta)
return "";
return meta->getOwner();
}
break;
default:
assert(0);
}
return "";
}
void Server::setInventoryModified(const InventoryLocation &loc)
{
switch(loc.type){
@ -3272,10 +3207,6 @@ void Server::setInventoryModified(const InventoryLocation &loc)
{
v3s16 blockpos = getNodeBlockPos(loc.p);
NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
if(meta)
meta->inventoryModified();
MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
if(block)
block->raiseModified(MOD_STATE_WRITE_NEEDED);

@ -483,7 +483,6 @@ public:
Shall be called with the environment and the connection locked.
*/
Inventory* getInventory(const InventoryLocation &loc);
std::string getInventoryOwner(const InventoryLocation &loc);
void setInventoryModified(const InventoryLocation &loc);
// Connection must be locked when called