campfire pt1

This commit is contained in:
darkrose 2017-02-08 02:02:00 +10:00
parent 4a91f12ff0
commit bdb7493ccc
16 changed files with 481 additions and 16 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -39,6 +39,8 @@ struct CraftItemFeatures {
std::wstring description;
// the result of cooking this item
content_t cook_result;
// what type of cooking device this item needs
CookType cook_type;
// the fuel value of this item
float fuel_time;
// whether the item can be stacked in inventory
@ -82,6 +84,7 @@ struct CraftItemFeatures {
name(""),
description(L""),
cook_result(CONTENT_IGNORE),
cook_type(COOK_ANY),
fuel_time(0.0),
stackable(true),
consumable(false),

View File

@ -6365,6 +6365,101 @@ void meshgen_melonlike(MeshMakeData *data, v3s16 p, MapNode &n, SelectedNode &se
meshgen_build_nodebox(data,p,n,selected,boxes,tiles);
}
void meshgen_campfirelike(MeshMakeData *data, v3s16 p, MapNode &n, SelectedNode &selected)
{
TileSpec stone_tiles[6];
TileSpec wood_tiles[6];
TileSpec fire_tile;
ContentFeatures *f;
std::vector<NodeBox> boxes;
f = &content_features(n.getContent());
fire_tile = f->tiles[2];
for (u16 i=0; i<6; i++) {
stone_tiles[i] = f->tiles[0];
wood_tiles[i] = f->tiles[1];
}
boxes.push_back(NodeBox(
-0.5*data->m_BS,-0.5*data->m_BS,-0.125*data->m_BS,-0.3125*data->m_BS,-0.375*data->m_BS,0.125*data->m_BS
));
boxes.push_back(NodeBox(
v3s16(0,45,0),v3f(0,0,0),-0.5*data->m_BS,-0.5*data->m_BS,-0.125*data->m_BS,-0.3125*data->m_BS,-0.375*data->m_BS,0.125*data->m_BS
));
boxes.push_back(NodeBox(
-0.125*data->m_BS,-0.5*data->m_BS,0.3125*data->m_BS,0.125*data->m_BS,-0.375*data->m_BS,0.5*data->m_BS
));
boxes.push_back(NodeBox(
v3s16(0,45,0),v3f(0,0,0),-0.125*data->m_BS,-0.5*data->m_BS,0.3125*data->m_BS,0.125*data->m_BS,-0.375*data->m_BS,0.5*data->m_BS
));
boxes.push_back(NodeBox(
0.3125*data->m_BS,-0.5*data->m_BS,-0.125*data->m_BS,0.5*data->m_BS,-0.375*data->m_BS,0.125*data->m_BS
));
boxes.push_back(NodeBox(
v3s16(0,45,0),v3f(0,0,0),0.3125*data->m_BS,-0.5*data->m_BS,-0.125*data->m_BS,0.5*data->m_BS,-0.375*data->m_BS,0.125*data->m_BS
));
boxes.push_back(NodeBox(
-0.125*data->m_BS,-0.5*data->m_BS,-0.5*data->m_BS,0.125*data->m_BS,-0.375*data->m_BS,-0.3125*data->m_BS
));
boxes.push_back(NodeBox(
v3s16(0,45,0),v3f(0,0,0),-0.125*data->m_BS,-0.5*data->m_BS,-0.5*data->m_BS,0.125*data->m_BS,-0.375*data->m_BS,-0.3125*data->m_BS
));
meshgen_build_nodebox(data,p,n,selected,boxes,stone_tiles);
boxes.clear();
boxes.push_back(NodeBox(
v3s16(0,0,-20),v3f(0,0,0),-0.125*data->m_BS,-0.5*data->m_BS,-0.0625*data->m_BS,0.0*data->m_BS,-0.0625*data->m_BS,0.0625*data->m_BS
));
boxes.push_back(NodeBox(
v3s16(0,0,20),v3f(0,0,0),0.0*data->m_BS,-0.5*data->m_BS,-0.0625*data->m_BS,0.125*data->m_BS,-0.0625*data->m_BS,0.0625*data->m_BS
));
boxes.push_back(NodeBox(
v3s16(20,0,0),v3f(0,0,0),-0.0625*data->m_BS,-0.5*data->m_BS,-0.125*data->m_BS,0.0625*data->m_BS,-0.0625*data->m_BS,0.0*data->m_BS
));
boxes.push_back(NodeBox(
v3s16(-20,0,0),v3f(0,0,0),-0.0625*data->m_BS,-0.5*data->m_BS,0.0*data->m_BS,0.0625*data->m_BS,-0.0625*data->m_BS,0.125*data->m_BS
));
meshgen_build_nodebox(data,p,n,selected,boxes,wood_tiles);
if (selected.is_coloured || selected.has_crack)
return;
v3f pos = intToFloat(p,BS);
for (u32 j=0; j<2; j++) {
video::S3DVertex vertices[4] = {
video::S3DVertex(-0.5*BS,-0.5*BS,0., 0,0,0, video::SColor(255,255,255,255), 0.,1.),
video::S3DVertex( 0.5*BS,-0.5*BS,0., 0,0,0, video::SColor(255,255,255,255), 1.,1.),
video::S3DVertex( 0.5*BS, 0.5*BS,0., 0,0,0, video::SColor(255,255,255,255), 1.,0.),
video::S3DVertex(-0.5*BS, 0.5*BS,0., 0,0,0, video::SColor(255,255,255,255), 0.,0.)
};
s16 angle = 45;
if (j == 1)
angle = -45;
for (u16 i=0; i<4; i++) {
vertices[i].Pos.rotateXZBy(angle);
vertices[i].TCoords *= fire_tile.texture.size;
vertices[i].TCoords += fire_tile.texture.pos;
}
u16 indices[] = {0,1,2,2,3,0};
std::vector<u32> colours;
meshgen_lights(data,n,p,colours,255,v3s16(0,0,0),4,vertices);
for (u16 i=0; i<4; i++) {
vertices[i].Pos += pos;
}
data->append(fire_tile, vertices, 4, indices, 6, colours);
}
}
void meshgen_farnode(MeshMakeData *data, v3s16 p, MapNode &n)
{
SelectedNode selected;

View File

@ -53,6 +53,7 @@ void meshgen_slablike(MeshMakeData *data, v3s16 p, MapNode &n, SelectedNode &sel
void meshgen_trunklike(MeshMakeData *data, v3s16 p, MapNode &n, SelectedNode &selected);
void meshgen_flaglike(MeshMakeData *data, v3s16 p, MapNode &n, SelectedNode &selected);
void meshgen_melonlike(MeshMakeData *data, v3s16 p, MapNode &n, SelectedNode &selected);
void meshgen_campfirelike(MeshMakeData *data, v3s16 p, MapNode &n, SelectedNode &selected);
void meshgen_farnode(MeshMakeData *data, v3s16 p, MapNode &n);
#endif

View File

@ -95,7 +95,8 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
// more walls
#define CONTENT_LIMESTONE_WALL 0x02C
#define CONTENT_MARBLE_WALL 0x02D
// FREE 0x02E-0x07C
#define CONTENT_CAMPFIRE 0x02E
// FREE 0x02F-0x07C
// 0x7D-0x7F reserved values, air, ignore, etc
#define CONTENT_CHAIR_CENTRE 0x080
#define CONTENT_CHAIR_ENDL 0x081

View File

@ -1467,6 +1467,49 @@ void content_mapnode_special(bool repeat)
f->hardness = 0.4;
f->pressure_type = CST_SOLID;
i = CONTENT_CAMPFIRE;
f = &content_features(i);
f->description = wgettext("Camp Fire");
f->draw_type = CDT_CAMPFIRELIKE;
f->param_type = CPT_LIGHT;
f->draw_type = CDT_CAMPFIRELIKE;
f->light_propagates = true;
f->sunlight_propagates = true;
f->walkable = false;
f->fuel_time = 1.0;
f->light_source = LIGHT_MAX-1;
f->damage_per_second = 40;
f->setAllTextures("campfire_stones.png");
f->setTexture(0, "campfire_stones.png");
f->setTexture(1, "campfire_logs.png");
#ifndef SERVER
f->animation_length = 1.0;
f->setTextureFlags(2, MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES);
#endif
f->setTexture(2, "campfire_flame.png");
content_nodebox_roofcollide(f);
f->setInventoryTexture("campfire_inv.png");
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
if(f->initial_metadata == NULL)
f->initial_metadata = new CampFireNodeMetadata();
f->type = CMT_WOOD;
f->hardness = 2.0;
f->pressure_type = CST_CRUSHED;
{
u16 r[9] = {
CONTENT_ROCK, CONTENT_WOOD, CONTENT_ROCK,
CONTENT_WOOD, CONTENT_IGNORE, CONTENT_WOOD,
CONTENT_ROCK, CONTENT_WOOD, CONTENT_ROCK
};
crafting::setRecipe(r,CONTENT_CAMPFIRE,1);
}
lists::add("craftguide",i);
lists::add("creative",i);
i = CONTENT_NC;
f = &content_features(i);
f->description = wgettext("Nyan Cat");

View File

@ -923,7 +923,7 @@ std::wstring FurnaceNodeMetadata::infoText()
assert(src_list);
const InventoryItem *src_item = src_list->getItem(0);
if (src_item && src_item->isCookable()) {
if (src_item && src_item->isCookable(COOK_FURNACE)) {
InventoryList *dst_list = m_inventory->getList("dst");
if(!dst_list->roomForCookedItem(src_item))
return wgettext("Furnace is overloaded");
@ -994,7 +994,7 @@ bool FurnaceNodeMetadata::step(float dtime, v3s16 pos, ServerEnvironment *env)
bool room_available = false;
if (src_item && src_item->isCookable())
if (src_item && src_item->isCookable(COOK_FURNACE))
room_available = dst_list->roomForCookedItem(src_item);
// Start only if there are free slots in dst, so that it can
@ -1188,7 +1188,7 @@ std::wstring LockingFurnaceNodeMetadata::infoText()
assert(src_list);
const InventoryItem *src_item = src_list->getItem(0);
if(src_item && src_item->isCookable()) {
if(src_item && src_item->isCookable(COOK_FURNACE)) {
InventoryList *dst_list = m_inventory->getList("dst");
if (!dst_list->roomForCookedItem(src_item))
return wgettext("Locking Furnace is overloaded")+std::wstring(L" (")+narrow_to_wide(ostr)+L")";
@ -1260,7 +1260,7 @@ bool LockingFurnaceNodeMetadata::step(float dtime, v3s16 pos, ServerEnvironment
bool room_available = false;
if (src_item && src_item->isCookable()) {
if (src_item && src_item->isCookable(COOK_FURNACE)) {
room_available = dst_list->roomForCookedItem(src_item);
m_lock = 300.0;
changed = true;
@ -1384,6 +1384,253 @@ bool LockingFurnaceNodeMetadata::import(NodeMetadata *meta)
return true;
}
/*
CampFireNodeMetadata
*/
// Prototype
CampFireNodeMetadata proto_CampFireNodeMetadata;
CampFireNodeMetadata::CampFireNodeMetadata()
{
NodeMetadata::registerType(typeId(), create);
m_inventory = new Inventory();
m_inventory->addList("fuel", 1);
m_inventory->addList("src", 1);
m_inventory->addList("dst", 4);
m_step_accumulator = 0;
m_fuel_totaltime = 0;
m_fuel_time = 0;
m_src_totaltime = 0;
m_src_time = 0;
}
CampFireNodeMetadata::~CampFireNodeMetadata()
{
delete m_inventory;
}
u16 CampFireNodeMetadata::typeId() const
{
return CONTENT_CAMPFIRE;
}
NodeMetadata* CampFireNodeMetadata::clone()
{
CampFireNodeMetadata *d = new CampFireNodeMetadata();
*d->m_inventory = *m_inventory;
d->m_fuel_totaltime = m_fuel_totaltime;
d->m_fuel_time = m_fuel_time;
d->m_src_totaltime = m_src_totaltime;
d->m_src_time = m_src_time;
return d;
}
NodeMetadata* CampFireNodeMetadata::create(std::istream &is)
{
CampFireNodeMetadata *d = new CampFireNodeMetadata();
d->m_inventory->deSerialize(is);
int temp;
is>>temp;
d->m_fuel_totaltime = (float)temp/10;
is>>temp;
d->m_fuel_time = (float)temp/10;
return d;
}
void CampFireNodeMetadata::serializeBody(std::ostream &os)
{
m_inventory->serialize(os);
os<<itos(m_fuel_totaltime*10)<<" ";
os<<itos(m_fuel_time*10)<<" ";
}
std::wstring CampFireNodeMetadata::infoText()
{
//return "CampFire";
if (m_fuel_time >= m_fuel_totaltime) {
const InventoryList *src_list = m_inventory->getList("src");
assert(src_list);
const InventoryItem *src_item = src_list->getItem(0);
if (src_item && src_item->isCookable(COOK_FIRE)) {
InventoryList *dst_list = m_inventory->getList("dst");
if(!dst_list->roomForCookedItem(src_item))
return wgettext("CampFire is overloaded");
return wgettext("CampFire is out of fuel");
}else{
return wgettext("CampFire is inactive");
}
}else{
std::wstring s = wgettext("CampFire is active");
// Do this so it doesn't always show (0%) for weak fuel
if (m_fuel_totaltime > 3) {
s += L" (";
s += itows(m_fuel_time/m_fuel_totaltime*100);
s += L"%)";
}
return s;
}
}
bool CampFireNodeMetadata::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 CampFireNodeMetadata::inventoryModified()
{
infostream<<"CampFire inventory modification callback"<<std::endl;
}
bool CampFireNodeMetadata::step(float dtime, v3s16 pos, ServerEnvironment *env)
{
{
MapNode n = env->getMap().getNodeNoEx(pos).getContent();
if (n.getContent() == CONTENT_FURNACE_ACTIVE) {
n.param1 = n.param2;
n.setContent(CONTENT_FURNACE);
env->setPostStepNodeSwap(pos,n);
}
}
if (dtime > 60.0)
infostream<<"CampFire stepping a long time ("<<dtime<<")"<<std::endl;
// 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;
InventoryList *dst_list = m_inventory->getList("dst");
assert(dst_list);
InventoryList *src_list = m_inventory->getList("src");
assert(src_list);
InventoryItem *src_item = src_list->getItem(0);
bool room_available = false;
if (src_item && src_item->isCookable(COOK_FIRE))
room_available = dst_list->roomForCookedItem(src_item);
// Start only if there are free slots in dst, so that it can
// accomodate any result item
if (room_available) {
m_src_totaltime = 3;
}else{
m_src_time = 0;
m_src_totaltime = 0;
}
/*
If fuel is burning, increment the burn counters.
If item finishes cooking, move it to result.
*/
if (m_fuel_time < m_fuel_totaltime) {
m_fuel_time += dtime;
m_src_time += dtime;
if (m_src_time >= m_src_totaltime && m_src_totaltime > 0.001 && src_item) {
InventoryItem *cookresult = src_item->createCookResult();
dst_list->addItem(cookresult);
src_list->decrementMaterials(1);
m_src_time = 0;
m_src_totaltime = 0;
}
changed = true;
// If the fuel was not used up this step, just keep burning it
if (m_fuel_time < m_fuel_totaltime)
continue;
}
/*
Get the source again in case it has all burned
*/
src_item = src_list->getItem(0);
/*
If there is no source item, or the source item is not cookable,
or the furnace is still cooking, or the furnace became overloaded, stop loop.
*/
if (
src_item == NULL
|| !room_available
|| m_fuel_time < m_fuel_totaltime
|| dst_list->roomForCookedItem(src_item) == false
) {
m_step_accumulator = 0;
break;
}
//infostream<<"CampFire is out of fuel"<<std::endl;
InventoryList *fuel_list = m_inventory->getList("fuel");
assert(fuel_list);
InventoryItem *fuel_item = fuel_list->getItem(0);
if (fuel_item && fuel_item->isFuel()) {
if ((fuel_item->getContent()&CONTENT_CRAFTITEM_MASK) == CONTENT_CRAFTITEM_MASK) {
m_fuel_totaltime = ((CraftItem*)fuel_item)->getFuelTime();
}else if ((fuel_item->getContent()&CONTENT_TOOLITEM_MASK) == CONTENT_TOOLITEM_MASK) {
m_fuel_totaltime = ((ToolItem*)fuel_item)->getFuelTime();
}else{
m_fuel_totaltime = ((MaterialItem*)fuel_item)->getFuelTime();
}
m_fuel_totaltime *= 2.0;
m_fuel_time = 0;
content_t c = fuel_item->getContent();
fuel_list->decrementMaterials(1);
if (c == CONTENT_TOOLITEM_STEELBUCKET_LAVA) {
fuel_list->addItem(0,new ToolItem(CONTENT_TOOLITEM_STEELBUCKET,0,0));
}
changed = true;
}else{
m_step_accumulator = 0;
}
}
return changed;
}
std::string CampFireNodeMetadata::getDrawSpecString(Player *player)
{
std::string spec("size[8,9]");
spec += "list[current_name;fuel;2,3;1,1;]";
spec += "ring[2,3;1;#FF0000;";
float v = 0;
if (m_fuel_totaltime > 0.0)
v = 100.0-((100.0/m_fuel_totaltime)*m_fuel_time);
spec += itos((int)v);
spec += "]";
spec += "list[current_name;src;2,1;1,1;]";
spec += "list[current_name;dst;5,1;2,2;]";
spec += "list[current_player;main;0,5;8,4;]";
return spec;
}
std::vector<NodeBox> CampFireNodeMetadata::getNodeBoxes(MapNode &n)
{
std::vector<NodeBox> boxes;
boxes.clear();
if (m_fuel_time < m_fuel_totaltime) {
boxes.push_back(NodeBox(
-0.3125*BS,-0.25*BS,-0.4*BS,0.3125*BS,0.125*BS,-0.3*BS
));
}
return transformNodeBox(n,boxes);
}
/*
LockedDoorNodeMetadata
*/

View File

@ -314,6 +314,33 @@ private:
float m_src_time;
};
class CampFireNodeMetadata : public NodeMetadata
{
public:
CampFireNodeMetadata();
~CampFireNodeMetadata();
virtual u16 typeId() const;
virtual NodeMetadata* clone();
static NodeMetadata* create(std::istream &is);
virtual void serializeBody(std::ostream &os);
virtual std::wstring infoText();
virtual Inventory* getInventory() {return m_inventory;}
virtual void inventoryModified();
virtual bool step(float dtime, v3s16 pos, ServerEnvironment *env);
virtual bool nodeRemovalDisabled();
virtual std::string getDrawSpecString(Player *player);
virtual std::vector<NodeBox> getNodeBoxes(MapNode &n);
private:
Inventory *m_inventory;
float m_step_accumulator;
float m_fuel_totaltime;
float m_fuel_time;
float m_src_totaltime;
float m_src_time;
};
class LockingFurnaceNodeMetadata : public NodeMetadata
{
public:

View File

@ -27,6 +27,8 @@ struct ToolItemFeatures {
std::wstring description;
// the result of cooking this item
std::string cook_result;
// what type of cooking device this item needs
CookType cook_type;
// the fuel value of this item
float fuel_time;
// 0 if inedible, otherwise the value it improves hp by
@ -69,6 +71,7 @@ struct ToolItemFeatures {
name(""),
description(L""),
cook_result(""),
cook_type(COOK_ANY),
fuel_time(0.0),
edible(0),
drop_count(-1),

View File

@ -32,6 +32,8 @@
#include "main.h"
#include "serverobject.h"
#include "content_mapnode.h"
#include "content_craftitem.h"
#include "content_toolitem.h"
#include "content_sao.h"
#include "content_mob.h"
#include "player.h"
@ -255,9 +257,16 @@ std::wstring MaterialItem::getGuiText()
return txt;
}
bool MaterialItem::isCookable() const
bool MaterialItem::isCookable(CookType type) const
{
return (content_features(m_content).cook_result != "");
ContentFeatures *f = &content_features(m_content);
if (!f)
return false;
if (type != f->cook_type && f->cook_type != COOK_ANY)
return false;
if (f->cook_result == "")
return false;
return true;
}
InventoryItem *MaterialItem::createCookResult() const
@ -417,9 +426,16 @@ u16 CraftItem::getDropCount() const
return InventoryItem::getDropCount();
}
bool CraftItem::isCookable() const
bool CraftItem::isCookable(CookType type) const
{
return content_craftitem_features(m_content).cook_result != CONTENT_IGNORE;
CraftItemFeatures *f = &content_craftitem_features(m_content);
if (!f)
return false;
if (type != f->cook_type && f->cook_type != COOK_ANY)
return false;
if (f->cook_result == CONTENT_IGNORE)
return false;
return true;
}
InventoryItem *CraftItem::createCookResult() const
@ -575,9 +591,16 @@ std::wstring ToolItem::getGuiText()
return txt;
}
bool ToolItem::isCookable() const
bool ToolItem::isCookable(CookType type) const
{
return content_toolitem_features(m_content).cook_result != "";
ToolItemFeatures *f = &content_toolitem_features(m_content);
if (!f)
return false;
if (type != f->cook_type && f->cook_type != COOK_ANY)
return false;
if (f->cook_result == "")
return false;
return true;
}
InventoryItem *ToolItem::createCookResult() const

View File

@ -134,7 +134,7 @@ public:
*/
// Whether it can be cooked
virtual bool isCookable() const {return false;}
virtual bool isCookable(CookType type=COOK_ANY) const {return false;}
// Time of cooking
virtual float getCookTime() const {return 3.0;}
// Result of cooking (can randomize)
@ -221,7 +221,7 @@ public:
/*
Other properties
*/
bool isCookable() const;
bool isCookable(CookType type) const;
InventoryItem *createCookResult() const;
virtual bool isFuel() const;
virtual float getFuelTime() const;
@ -319,7 +319,7 @@ public:
Other properties
*/
bool isCookable() const;
bool isCookable(CookType type) const;
InventoryItem *createCookResult() const;
bool isFuel() const;
float getFuelTime() const;
@ -400,7 +400,7 @@ public:
ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos);
bool isCookable() const;
bool isCookable(CookType type) const;
InventoryItem *createCookResult() const;
bool isFuel() const;
float getFuelTime() const;

View File

@ -664,6 +664,11 @@ void MapBlockMesh::generate(MeshMakeData *data, v3s16 camera_offset, JMutex *mut
meshgen_melonlike(data,p,n,selected);
meshgen_farnode(data,p,n);
break;
case CDT_CAMPFIRELIKE:
meshgen_campfirelike(data,p,n,selected);
break;
case CDT_BUSHLIKE:
break;
default:;
}
}

View File

@ -120,7 +120,9 @@ enum ContentDrawType
CDT_SLABLIKE,
CDT_TRUNKLIKE,
CDT_DIRTLIKE,
CDT_FLAGLIKE
CDT_FLAGLIKE,
CDT_CAMPFIRELIKE,
CDT_BUSHLIKE
};
/*
@ -150,6 +152,13 @@ enum LiquidType
LIQUID_SOURCE
};
enum CookType
{
COOK_ANY,
COOK_FIRE,
COOK_FURNACE
};
/*
Material Type
*/
@ -436,6 +445,8 @@ struct ContentFeatures
// the result of cooking this node
std::string cook_result;
// what type of cooking device this node needs
CookType cook_type;
// the fuel value of this node
float fuel_time;
@ -578,6 +589,7 @@ struct ContentFeatures
powered_node = CONTENT_IGNORE;
unpowered_node = CONTENT_IGNORE;
cook_result = "";
cook_type = COOK_ANY;
fuel_time = 0.0;
plantgrowth_max_height = 1;
plantgrowth_small_dug_node = CONTENT_IGNORE;

View File

@ -297,6 +297,11 @@ void SelectionMesh::generate(MeshMakeData *data)
case CDT_MELONLIKE:
meshgen_melonlike(data,p,n,selected);
break;
case CDT_CAMPFIRELIKE:
meshgen_campfirelike(data,p,n,selected);
break;
case CDT_BUSHLIKE:
break;
default:;
}
}