mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 10:03:45 +01:00
WIP node metadata, node timers
This commit is contained in:
parent
67059e1932
commit
704782c95b
@ -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
|
||||
{
|
||||
|
50
src/map.cpp
50
src/map.cpp
@ -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
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
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
|
||||
|
Loading…
Reference in New Issue
Block a user