1,251 changes: 768 additions & 483 deletions data/mods/default/init.lua

Large diffs are not rendered by default.

48 changes: 9 additions & 39 deletions data/mods/experimental/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ minetest.register_globalstep(on_step)

-- An example furnace-thing implemented in Lua

--[[
minetest.register_node("experimental:luafurnace", {
tile_images = {"default_lava.png", "default_furnace_side.png",
"default_furnace_side.png", "default_furnace_side.png",
Expand Down Expand Up @@ -56,15 +57,6 @@ minetest.register_on_placenode(function(pos, newnode, placer)
end
end)
local get_item_definition = function(item)
if not item then return nil end
if item.type == "node" then
return minetest.registered_nodes[item.name]
elseif item.type == "craft" then
return minetest.registered_craftitems[item.name]
end
end

minetest.register_abm({
nodenames = {"experimental:luafurnace"},
interval = 1.0,
Expand Down Expand Up @@ -176,7 +168,6 @@ minetest.register_abm({
inv:set_stack("fuel", 1, stack)
end,
})
--[[
minetest.register_abm({
nodenames = {"experimental:luafurnace"},
interval = 1.0,
Expand Down Expand Up @@ -231,7 +222,6 @@ minetest.register_abm({
meta:set_infotext("Lua Furnace: total cooked: "..total_cooked)
end,
})
--]]
minetest.register_craft({
output = 'node "experimental:luafurnace" 1',
recipe = {
Expand All @@ -240,6 +230,7 @@ minetest.register_craft({
{'node "default:cobble"', 'node "default:cobble"', 'node "default:cobble"'},
}
})
--]]

--
-- Random stuff
Expand All @@ -261,38 +252,16 @@ minetest.register_tool("experimental:horribletool", {
})
--]]

--[[minetest.register_craft({
output = 'node "somenode" 4',
recipe = {
{'craft "default_tick" 1'},
}
})
minetest.register_node("experimental:somenode", {
tile_images = {"lava.png", "mese.png", "stone.png", "grass.png", "cobble.png", "tree_top.png"},
inventory_image = minetest.inventorycube("lava.png", "mese.png", "stone.png"),
--inventory_image = "treeprop.png",
material = {
diggability = "normal",
weight = 0,
crackiness = 0,
crumbliness = 0,
cuttability = 0,
flammability = 0
},
metadata_name = "chest",
})]]

--
-- TNT (not functional)
--

minetest.register_craft({
output = 'node "experimental:tnt" 4',
output = 'experimental:tnt',
recipe = {
{'node "default:wood" 1'},
{'craft "default:coal_lump" 1'},
{'node "default:wood" 1'}
{'default:wood'},
{'default:coal_lump'},
{'default:wood'}
}
})

Expand Down Expand Up @@ -363,7 +332,7 @@ function TNT:on_punch(hitter)
self.health = self.health - 1
if self.health <= 0 then
self.object:remove()
hitter:add_to_inventory("node TNT 1")
hitter:get_inventory():add_item("main", "experimental:tnt")
hitter:set_hp(hitter:get_hp() - 1)
end
end
Expand All @@ -380,7 +349,7 @@ end
minetest.register_entity("experimental:tnt", TNT)

-- Add TNT's old name also
minetest.alias_node("TNT", "experimental:tnt")
minetest.register_alias("TNT", "experimental:tnt")

--
-- A test entity for testing animated and yaw-modulated sprites
Expand Down Expand Up @@ -547,6 +516,7 @@ minetest.register_abm({
end,
})--]]

print("experimental modname="..dump(minetest.get_current_modname()))
print("experimental modpath="..dump(minetest.get_modpath("experimental")))

-- END
171 changes: 100 additions & 71 deletions data/mods/legacy/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,97 +5,126 @@
-- Aliases to support loading 0.3 and old 0.4 worlds and inventories
--

minetest.alias_node("stone", "default:stone")
minetest.alias_node("dirt_with_grass", "default:dirt_with_grass")
minetest.alias_node("dirt_with_grass_footsteps", "default:dirt_with_grass_footsteps")
minetest.alias_node("dirt", "default:dirt")
minetest.alias_node("sand", "default:sand")
minetest.alias_node("gravel", "default:gravel")
minetest.alias_node("sandstone", "default:sandstone")
minetest.alias_node("clay", "default:clay")
minetest.alias_node("brick", "default:brick")
minetest.alias_node("tree", "default:tree")
minetest.alias_node("jungletree", "default:jungletree")
minetest.alias_node("junglegrass", "default:junglegrass")
minetest.alias_node("leaves", "default:leaves")
minetest.alias_node("cactus", "default:cactus")
minetest.alias_node("papyrus", "default:papyrus")
minetest.alias_node("bookshelf", "default:bookshelf")
minetest.alias_node("glass", "default:glass")
minetest.alias_node("wooden_fence", "default:fence_wood")
minetest.alias_node("rail", "default:rail")
minetest.alias_node("ladder", "default:ladder")
minetest.alias_node("wood", "default:wood")
minetest.alias_node("mese", "default:mese")
minetest.alias_node("cloud", "default:cloud")
minetest.alias_node("water_flowing", "default:water_flowing")
minetest.alias_node("water_source", "default:water_source")
minetest.alias_node("lava_flowing", "default:lava_flowing")
minetest.alias_node("lava_source", "default:lava_source")
minetest.alias_node("torch", "default:torch")
minetest.alias_node("sign_wall", "default:sign_wall")
minetest.alias_node("furnace", "default:furnace")
minetest.alias_node("chest", "default:chest")
minetest.alias_node("locked_chest", "default:chest_locked")
minetest.alias_node("cobble", "default:cobble")
minetest.alias_node("mossycobble", "default:mossycobble")
minetest.alias_node("steelblock", "default:steelblock")
minetest.alias_node("nyancat", "default:nyancat")
minetest.alias_node("nyancat_rainbow", "default:nyancat_rainbow")
minetest.alias_node("sapling", "default:sapling")
minetest.alias_node("apple", "default:apple")
minetest.register_alias("stone", "default:stone")
minetest.register_alias("dirt_with_grass", "default:dirt_with_grass")
minetest.register_alias("dirt_with_grass_footsteps", "default:dirt_with_grass_footsteps")
minetest.register_alias("dirt", "default:dirt")
minetest.register_alias("sand", "default:sand")
minetest.register_alias("gravel", "default:gravel")
minetest.register_alias("sandstone", "default:sandstone")
minetest.register_alias("clay", "default:clay")
minetest.register_alias("brick", "default:brick")
minetest.register_alias("tree", "default:tree")
minetest.register_alias("jungletree", "default:jungletree")
minetest.register_alias("junglegrass", "default:junglegrass")
minetest.register_alias("leaves", "default:leaves")
minetest.register_alias("cactus", "default:cactus")
minetest.register_alias("papyrus", "default:papyrus")
minetest.register_alias("bookshelf", "default:bookshelf")
minetest.register_alias("glass", "default:glass")
minetest.register_alias("wooden_fence", "default:fence_wood")
minetest.register_alias("rail", "default:rail")
minetest.register_alias("ladder", "default:ladder")
minetest.register_alias("wood", "default:wood")
minetest.register_alias("mese", "default:mese")
minetest.register_alias("cloud", "default:cloud")
minetest.register_alias("water_flowing", "default:water_flowing")
minetest.register_alias("water_source", "default:water_source")
minetest.register_alias("lava_flowing", "default:lava_flowing")
minetest.register_alias("lava_source", "default:lava_source")
minetest.register_alias("torch", "default:torch")
minetest.register_alias("sign_wall", "default:sign_wall")
minetest.register_alias("furnace", "default:furnace")
minetest.register_alias("chest", "default:chest")
minetest.register_alias("locked_chest", "default:chest_locked")
minetest.register_alias("cobble", "default:cobble")
minetest.register_alias("mossycobble", "default:mossycobble")
minetest.register_alias("steelblock", "default:steelblock")
minetest.register_alias("nyancat", "default:nyancat")
minetest.register_alias("nyancat_rainbow", "default:nyancat_rainbow")
minetest.register_alias("sapling", "default:sapling")
minetest.register_alias("apple", "default:apple")

minetest.alias_tool("WPick", "default:pick_wood")
minetest.alias_tool("STPick", "default:pick_stone")
minetest.alias_tool("SteelPick", "default:pick_steel")
minetest.alias_tool("MesePick", "default:pick_mese")
minetest.alias_tool("WShovel", "default:shovel_wood")
minetest.alias_tool("STShovel", "default:shovel_stone")
minetest.alias_tool("SteelShovel", "default:shovel_steel")
minetest.alias_tool("WAxe", "default:axe_wood")
minetest.alias_tool("STAxe", "default:axe_stone")
minetest.alias_tool("SteelAxe", "default:axe_steel")
minetest.alias_tool("WSword", "default:sword_wood")
minetest.alias_tool("STSword", "default:sword_stone")
minetest.alias_tool("SteelSword", "default:sword_steel")
minetest.register_alias("WPick", "default:pick_wood")
minetest.register_alias("STPick", "default:pick_stone")
minetest.register_alias("SteelPick", "default:pick_steel")
minetest.register_alias("MesePick", "default:pick_mese")
minetest.register_alias("WShovel", "default:shovel_wood")
minetest.register_alias("STShovel", "default:shovel_stone")
minetest.register_alias("SteelShovel", "default:shovel_steel")
minetest.register_alias("WAxe", "default:axe_wood")
minetest.register_alias("STAxe", "default:axe_stone")
minetest.register_alias("SteelAxe", "default:axe_steel")
minetest.register_alias("WSword", "default:sword_wood")
minetest.register_alias("STSword", "default:sword_stone")
minetest.register_alias("SteelSword", "default:sword_steel")

minetest.alias_craftitem("Stick", "default:stick")
minetest.alias_craftitem("paper", "default:paper")
minetest.alias_craftitem("book", "default:book")
minetest.alias_craftitem("lump_of_coal", "default:coal_lump")
minetest.alias_craftitem("lump_of_iron", "default:iron_lump")
minetest.alias_craftitem("lump_of_clay", "default:clay_lump")
minetest.alias_craftitem("steel_ingot", "default:steel_ingot")
minetest.alias_craftitem("clay_brick", "default:clay_brick")
minetest.alias_craftitem("scorched_stuff", "default:scorched_stuff")
minetest.alias_craftitem("apple", "default:apple")
minetest.register_alias("Stick", "default:stick")
minetest.register_alias("paper", "default:paper")
minetest.register_alias("book", "default:book")
minetest.register_alias("lump_of_coal", "default:coal_lump")
minetest.register_alias("lump_of_iron", "default:iron_lump")
minetest.register_alias("lump_of_clay", "default:clay_lump")
minetest.register_alias("steel_ingot", "default:steel_ingot")
minetest.register_alias("clay_brick", "default:clay_brick")
minetest.register_alias("scorched_stuff", "default:scorched_stuff")

--
-- Old items
--

minetest.register_craftitem(":rat", {
image = "rat.png",
cookresult_itemstring = 'craft "cooked_rat" 1',
description = "Rat",
inventory_image = "rat.png",
on_drop = function(item, dropper, pos)
minetest.env:add_rat(pos)
return true
item:take_item()
return item
end,
on_place = function(item, dropped, pointed)
pos = minetest.get_pointed_thing_position(pointed, true)
if pos ~= nil then
minetest.env:add_rat(pos)
item:take_item()
return item
end
end
})

minetest.register_craftitem(":cooked_rat", {
image = "cooked_rat.png",
cookresult_itemstring = 'craft "scorched_stuff" 1',
on_place_on_ground = minetest.craftitem_place_item,
on_use = minetest.craftitem_eat(6),
description = "Cooked rat",
inventory_image = "cooked_rat.png",
on_use = minetest.item_eat(6),
})

minetest.register_craftitem(":firefly", {
image = "firefly.png",
description = "Firefly",
inventory_image = "firefly.png",
on_drop = function(item, dropper, pos)
minetest.env:add_firefly(pos)
return true
item:take_item()
return item
end,
on_place = function(item, dropped, pointed)
pos = minetest.get_pointed_thing_position(pointed, true)
if pos ~= nil then
minetest.env:add_firefly(pos)
item:take_item()
return item
end
end
})

minetest.register_craft({
type = "cooking",
output = "cooked_rat",
recipe = "rat",
})

minetest.register_craft({
type = "cooking",
output = "scorched_stuff",
recipe = "cooked_rat",
})

-- END
3 changes: 1 addition & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,8 @@ set(common_SRCS
content_abm.cpp
craftdef.cpp
nameidmapping.cpp
tooldef.cpp
itemdef.cpp
nodedef.cpp
craftitemdef.cpp
luaentity_common.cpp
scriptapi.cpp
script.cpp
Expand Down
211 changes: 23 additions & 188 deletions src/camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "tile.h"
#include <cmath>
#include "settings.h"
#include "nodedef.h" // For wield visualization
#include "itemdef.h" // For wield visualization

Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control):
m_smgr(smgr),
Expand All @@ -37,6 +37,7 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control):

m_wieldmgr(NULL),
m_wieldnode(NULL),
m_wieldlight(0),

m_draw_control(draw_control),
m_viewing_range_min(5.0),
Expand Down Expand Up @@ -77,15 +78,15 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control):
// all other 3D scene nodes and before the GUI.
m_wieldmgr = smgr->createNewSceneManager();
m_wieldmgr->addCameraSceneNode();
m_wieldnode = new ExtrudedSpriteSceneNode(m_wieldmgr->getRootSceneNode(), m_wieldmgr);
m_wieldnode = m_wieldmgr->addMeshSceneNode(createCubeMesh(v3f(1,1,1)), NULL); // need a dummy mesh

updateSettings();
}

Camera::~Camera()
{
m_wieldnode->setMesh(NULL);
m_wieldmgr->drop();
m_wieldnode->drop();
}

bool Camera::successfullyCreated(std::wstring& error_message)
Expand Down Expand Up @@ -292,7 +293,7 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize)
}
m_wieldnode->setPosition(wield_position);
m_wieldnode->setRotation(wield_rotation);
m_wieldnode->updateLight(player->light);
m_wieldlight = player->light;

// Render distance feedback loop
updateViewingRange(frametime);
Expand Down Expand Up @@ -449,208 +450,42 @@ void Camera::updateSettings()
m_wanted_frametime = 1.0 / wanted_fps;
}

void Camera::wield(const InventoryItem* item, IGameDef *gamedef)
void Camera::setDigging(s32 button)
{
//ITextureSource *tsrc = gamedef->tsrc();
INodeDefManager *ndef = gamedef->ndef();
if (m_digging_button == -1)
m_digging_button = button;
}

if (item != NULL)
void Camera::wield(const ItemStack &item, IGameDef *gamedef)
{
IItemDefManager *idef = gamedef->idef();
scene::IMesh *wield_mesh = item.getDefinition(idef).wield_mesh;
if(wield_mesh)
{
bool isCube = false;

// Try to make a MaterialItem cube.
if (std::string(item->getName()) == "MaterialItem")
{
// A block-type material
MaterialItem* mat_item = (MaterialItem*) item;
content_t content = mat_item->getMaterial();
switch(ndef->get(content).drawtype){
case NDT_NORMAL:
case NDT_LIQUID:
case NDT_FLOWINGLIQUID:
case NDT_GLASSLIKE:
case NDT_ALLFACES:
case NDT_ALLFACES_OPTIONAL:
m_wieldnode->setCube(ndef->get(content).tiles);
isCube = true;
break;
default:
break;
}
}

// If that failed, make an extruded sprite.
if (!isCube)
{
m_wieldnode->setSprite(item->getImageRaw());
}

m_wieldnode->setMesh(wield_mesh);
m_wieldnode->setVisible(true);
}
else
{
// Bare hands
m_wieldnode->setSprite(gamedef->tsrc()->getTextureRaw("wieldhand.png"));
m_wieldnode->setVisible(true);
m_wieldnode->setVisible(false);
}
}

void Camera::setDigging(s32 button)
{
if (m_digging_button == -1)
m_digging_button = button;
}

void Camera::drawWieldedTool()
{
// Set vertex colors of wield mesh according to light level
u8 li = decode_light(m_wieldlight);
video::SColor color(255,li,li,li);
setMeshColor(m_wieldnode->getMesh(), color);

// Clear Z buffer
m_wieldmgr->getVideoDriver()->clearZBuffer();

// Draw the wielded node (in a separate scene manager)
scene::ICameraSceneNode* cam = m_wieldmgr->getActiveCamera();
cam->setAspectRatio(m_cameranode->getAspectRatio());
cam->setFOV(m_cameranode->getFOV());
cam->setNearValue(0.1);
cam->setFarValue(100);
m_wieldmgr->drawAll();
}


ExtrudedSpriteSceneNode::ExtrudedSpriteSceneNode(
scene::ISceneNode* parent,
scene::ISceneManager* mgr,
s32 id,
const v3f& position,
const v3f& rotation,
const v3f& scale
):
ISceneNode(parent, mgr, id, position, rotation, scale)
{
m_meshnode = mgr->addMeshSceneNode(NULL, this, -1, v3f(0,0,0), v3f(0,0,0), v3f(1,1,1), true);
m_cubemesh = NULL;
m_is_cube = false;
m_light = LIGHT_MAX;
}

ExtrudedSpriteSceneNode::~ExtrudedSpriteSceneNode()
{
removeChild(m_meshnode);
if (m_cubemesh)
m_cubemesh->drop();
}

void ExtrudedSpriteSceneNode::setSprite(video::ITexture* texture)
{
const v3f sprite_scale(40.0, 40.0, 4.0); // width, height, thickness

if (texture == NULL)
{
m_meshnode->setVisible(false);
return;
}

io::path name = getExtrudedName(texture);
scene::IMeshCache* cache = SceneManager->getMeshCache();
scene::IAnimatedMesh* mesh = cache->getMeshByName(name);
if (mesh != NULL)
{
// Extruded texture has been found in cache.
m_meshnode->setMesh(mesh);
}
else
{
// Texture was not yet extruded, do it now and save in cache
mesh = createExtrudedMesh(texture,
SceneManager->getVideoDriver(),
sprite_scale);
if (mesh == NULL)
{
dstream << "Warning: failed to extrude sprite" << std::endl;
m_meshnode->setVisible(false);
return;
}
cache->addMesh(name, mesh);
m_meshnode->setMesh(mesh);
mesh->drop();
}

m_meshnode->getMaterial(0).setTexture(0, texture);
m_meshnode->getMaterial(0).setFlag(video::EMF_LIGHTING, false);
m_meshnode->getMaterial(0).setFlag(video::EMF_BILINEAR_FILTER, false);
m_meshnode->getMaterial(0).MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
m_meshnode->setVisible(true);
m_is_cube = false;
updateLight(m_light);
}

void ExtrudedSpriteSceneNode::setCube(const TileSpec tiles[6])
{
const v3f cube_scale(30.0, 30.0, 30.0);

if (m_cubemesh == NULL)
{
m_cubemesh = createCubeMesh(cube_scale);
}

m_meshnode->setMesh(m_cubemesh);
for (int i = 0; i < 6; ++i)
{
// Get the tile texture and atlas transformation
video::ITexture* atlas = tiles[i].texture.atlas;
v2f pos = tiles[i].texture.pos;
v2f size = tiles[i].texture.size;

// Set material flags and texture
video::SMaterial& material = m_meshnode->getMaterial(i);
material.setFlag(video::EMF_LIGHTING, false);
material.setFlag(video::EMF_BILINEAR_FILTER, false);
tiles[i].applyMaterialOptions(material);
material.setTexture(0, atlas);
material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
}
m_meshnode->setVisible(true);
m_is_cube = true;
updateLight(m_light);
}

void ExtrudedSpriteSceneNode::updateLight(u8 light)
{
m_light = light;

u8 li = decode_light(light);
// Set brightness one lower than incoming light
diminish_light(li);
video::SColor color(255,li,li,li);
setMeshColor(m_meshnode->getMesh(), color);
}

void ExtrudedSpriteSceneNode::removeSpriteFromCache(video::ITexture* texture)
{
scene::IMeshCache* cache = SceneManager->getMeshCache();
scene::IAnimatedMesh* mesh = cache->getMeshByName(getExtrudedName(texture));
if (mesh != NULL)
cache->removeMesh(mesh);
}

const core::aabbox3d<f32>& ExtrudedSpriteSceneNode::getBoundingBox() const
{
return m_meshnode->getBoundingBox();
}

void ExtrudedSpriteSceneNode::OnRegisterSceneNode()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
}

void ExtrudedSpriteSceneNode::render()
{
// do nothing
}

io::path ExtrudedSpriteSceneNode::getExtrudedName(video::ITexture* texture)
{
io::path path = texture->getName();
path.append("/[extruded]");
return path;
}
54 changes: 5 additions & 49 deletions src/camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "tile.h"
#include "utility.h"
#include <ICameraSceneNode.h>
#include <IMeshCache.h>
#include <IAnimatedMesh.h>

class LocalPlayer;
struct MapDrawControl;
class ExtrudedSpriteSceneNode;
class IGameDef;

/*
Expand Down Expand Up @@ -116,13 +113,13 @@ class Camera
// Update settings from g_settings
void updateSettings();

// Replace the wielded item mesh
void wield(const InventoryItem* item, IGameDef *gamedef);

// Start digging animation
// Pass 0 for left click, 1 for right click
void setDigging(s32 button);

// Replace the wielded item mesh
void wield(const ItemStack &item, IGameDef *gamedef);

// Draw the wielded tool.
// This has to happen *after* the main scene is drawn.
// Warning: This clears the Z buffer.
Expand All @@ -136,7 +133,8 @@ class Camera
scene::ICameraSceneNode* m_cameranode;

scene::ISceneManager* m_wieldmgr;
ExtrudedSpriteSceneNode* m_wieldnode;
scene::IMeshSceneNode* m_wieldnode;
u8 m_wieldlight;

// draw control
MapDrawControl& m_draw_control;
Expand Down Expand Up @@ -182,46 +180,4 @@ class Camera
s32 m_digging_button;
};


/*
A scene node that displays a 2D mesh extruded into the third dimension,
to add an illusion of depth.
Since this class was created to display the wielded tool of the local
player, and only tools and items are rendered like this (but not solid
content like stone and mud, which are shown as cubes), the option to
draw a textured cube instead is provided.
*/
class ExtrudedSpriteSceneNode: public scene::ISceneNode
{
public:
ExtrudedSpriteSceneNode(
scene::ISceneNode* parent,
scene::ISceneManager* mgr,
s32 id = -1,
const v3f& position = v3f(0,0,0),
const v3f& rotation = v3f(0,0,0),
const v3f& scale = v3f(1,1,1));
~ExtrudedSpriteSceneNode();

void setSprite(video::ITexture* texture);
void setCube(const TileSpec tiles[6]);

void updateLight(u8 light);

void removeSpriteFromCache(video::ITexture* texture);

virtual const core::aabbox3d<f32>& getBoundingBox() const;
virtual void OnRegisterSceneNode();
virtual void render();

private:
scene::IMeshSceneNode* m_meshnode;
scene::IMesh* m_cubemesh;
bool m_is_cube;
u8 m_light;

io::path getExtrudedName(video::ITexture* texture);
};

#endif
261 changes: 90 additions & 171 deletions src/client.cpp

Large diffs are not rendered by default.

29 changes: 10 additions & 19 deletions src/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
struct MeshMakeData;
class IGameDef;
class IWritableTextureSource;
class IWritableToolDefManager;
class IWritableItemDefManager;
class IWritableNodeDefManager;
//class IWritableCraftDefManager;
class IWritableCraftItemDefManager;

class ClientNotReadyException : public BaseException
{
Expand Down Expand Up @@ -167,9 +166,8 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
std::string password,
MapDrawControl &control,
IWritableTextureSource *tsrc,
IWritableToolDefManager *tooldef,
IWritableNodeDefManager *nodedef,
IWritableCraftItemDefManager *craftitemdef
IWritableItemDefManager *itemdef,
IWritableNodeDefManager *nodedef
);

~Client();
Expand Down Expand Up @@ -245,11 +243,8 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
// Copies the inventory of the local player to parameter
void getLocalInventory(Inventory &dst);

InventoryContext *getInventoryContext();

/* InventoryManager interface */
Inventory* getInventory(const InventoryLocation &loc);
//Inventory* getInventory(InventoryContext *c, std::string id);
void inventoryAction(InventoryAction *a);

// Gets closest object pointed by the shootline
Expand Down Expand Up @@ -323,20 +318,19 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef

bool texturesReceived()
{ return m_textures_received; }
bool tooldefReceived()
{ return m_tooldef_received; }
bool itemdefReceived()
{ return m_itemdef_received; }
bool nodedefReceived()
{ return m_nodedef_received; }
bool craftitemdefReceived()
{ return m_craftitemdef_received; }

void afterContentReceived();

float getRTT(void);

// IGameDef interface
virtual IToolDefManager* getToolDefManager();
virtual IItemDefManager* getItemDefManager();
virtual INodeDefManager* getNodeDefManager();
virtual ICraftDefManager* getCraftDefManager();
virtual ICraftItemDefManager* getCraftItemDefManager();
virtual ITextureSource* getTextureSource();
virtual u16 allocateUnknownNodeId(const std::string &name);

Expand All @@ -363,9 +357,8 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
IntervalLimiter m_map_timer_and_unload_interval;

IWritableTextureSource *m_tsrc;
IWritableToolDefManager *m_tooldef;
IWritableItemDefManager *m_itemdef;
IWritableNodeDefManager *m_nodedef;
IWritableCraftItemDefManager *m_craftitemdef;
MeshUpdateThread m_mesh_update_thread;
ClientEnvironment m_env;
con::Connection m_con;
Expand All @@ -387,13 +380,11 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
std::string m_password;
bool m_access_denied;
std::wstring m_access_denied_reason;
InventoryContext m_inventory_context;
Queue<ClientEvent> m_client_event_queue;
float m_texture_receive_progress;
bool m_textures_received;
bool m_tooldef_received;
bool m_itemdef_received;
bool m_nodedef_received;
bool m_craftitemdef_received;
friend class FarMesh;
};

Expand Down
15 changes: 14 additions & 1 deletion src/clientserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Make players to be handled mostly as ActiveObjects
PROTOCOL_VERSION 6:
Only non-cached textures are sent
PROTOCOL_VERSION 7:
Add TOCLIENT_ITEMDEF
Obsolete TOCLIENT_TOOLDEF
Obsolete TOCLIENT_CRAFTITEMDEF
Compress the contents of TOCLIENT_ITEMDEF and TOCLIENT_NODEDEF
*/

#define PROTOCOL_VERSION 6
#define PROTOCOL_VERSION 7

#define PROTOCOL_ID 0x4f457403

Expand Down Expand Up @@ -252,6 +257,14 @@ enum ToClientCommand
string sha1_digest
}
*/

TOCLIENT_ITEMDEF = 0x3d,
/*
u16 command
u32 length of next item
serialized ItemDefManager
*/

};

enum ToServerCommand
Expand Down
6 changes: 1 addition & 5 deletions src/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -666,7 +666,7 @@ void Connection::send(float dtime)
// Receive packets from the network and buffers and create ConnectionEvents
void Connection::receive()
{
u32 datasize = 100000;
u32 datasize = m_max_packet_size * 2; // Double it just to be safe
// TODO: We can not know how many layers of header there are.
// For now, just assume there are no other than the base headers.
u32 packet_maxsize = datasize + BASE_HEADER_SIZE;
Expand Down Expand Up @@ -854,10 +854,6 @@ void Connection::receive()
dout_con<<"ProcessPacket returned data of size "
<<resultdata.getSize()<<std::endl;

if(datasize < resultdata.getSize())
throw InvalidIncomingDataException
("Buffer too small for received data");

ConnectionEvent e;
e.dataReceived(peer_id, resultdata);
putEvent(e);
Expand Down
107 changes: 60 additions & 47 deletions src/content_cao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "content_cao.h"
#include "tile.h"
#include "environment.h"
#include "collision.h"
#include "settings.h"
#include <ICameraSceneNode.h>
#include <ITextSceneNode.h>
Expand Down Expand Up @@ -172,6 +173,8 @@ class ItemCAO : public ClientActiveObject
void updateLight(u8 light_at_pos);
v3s16 getLightPosition();
void updateNodePos();
void updateInfoText();
void updateTexture();

void step(float dtime, ClientEnvironment *env);

Expand All @@ -191,7 +194,7 @@ class ItemCAO : public ClientActiveObject
core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_node;
v3f m_position;
std::string m_inventorystring;
std::string m_itemstring;
std::string m_infotext;
};

Expand Down Expand Up @@ -595,39 +598,13 @@ void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
buf->drop();
m_node = smgr->addMeshSceneNode(mesh, NULL);
mesh->drop();
// Set it to use the materials of the meshbuffers directly.
// This is needed for changing the texture in the future
m_node->setReadOnlyMaterials(true);
updateNodePos();

/*
Update image of node
*/

// Create an inventory item to see what is its image
std::istringstream is(m_inventorystring, std::ios_base::binary);
video::ITexture *texture = NULL;
try{
InventoryItem *item = NULL;
item = InventoryItem::deSerialize(is, m_gamedef);
infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
<<m_inventorystring<<"\" -> item="<<item
<<std::endl;
if(item)
{
texture = item->getImage();
delete item;
}
}
catch(SerializationError &e)
{
infostream<<"WARNING: "<<__FUNCTION_NAME
<<": error deSerializing inventorystring \""
<<m_inventorystring<<"\""<<std::endl;
}

// Set meshbuffer texture
buf->getMaterial().setTexture(0, texture);
updateTexture();
}

void ItemCAO::removeFromScene()
Expand Down Expand Up @@ -662,6 +639,51 @@ void ItemCAO::updateNodePos()
m_node->setPosition(m_position);
}

void ItemCAO::updateInfoText()
{
try{
IItemDefManager *idef = m_gamedef->idef();
ItemStack item;
item.deSerialize(m_itemstring, idef);
if(item.isKnown(idef))
m_infotext = item.getDefinition(idef).description;
else
m_infotext = "Unknown item: '" + m_itemstring + "'";
if(item.count >= 2)
m_infotext += " (" + itos(item.count) + ")";
}
catch(SerializationError &e)
{
m_infotext = "Unknown item: '" + m_itemstring + "'";
}
}

void ItemCAO::updateTexture()
{
if(m_node == NULL)
return;

// Create an inventory item to see what is its image
std::istringstream is(m_itemstring, std::ios_base::binary);
video::ITexture *texture = NULL;
try{
IItemDefManager *idef = m_gamedef->idef();
ItemStack item;
item.deSerialize(is, idef);
texture = item.getDefinition(idef).inventory_texture;
}
catch(SerializationError &e)
{
infostream<<"WARNING: "<<__FUNCTION_NAME
<<": error deSerializing itemstring \""
<<m_itemstring<<std::endl;
}

// Set meshbuffer texture
m_node->getMaterial(0).setTexture(0, texture);
}


void ItemCAO::step(float dtime, ClientEnvironment *env)
{
if(m_node)
Expand Down Expand Up @@ -689,6 +711,13 @@ void ItemCAO::processMessage(const std::string &data)
m_position = readV3F1000(is);
updateNodePos();
}
if(cmd == 1)
{
// itemstring
m_itemstring = deSerializeString(is);
updateInfoText();
updateTexture();
}
}

void ItemCAO::initialize(const std::string &data)
Expand All @@ -704,28 +733,12 @@ void ItemCAO::initialize(const std::string &data)
return;
// pos
m_position = readV3F1000(is);
// inventorystring
m_inventorystring = deSerializeString(is);
// itemstring
m_itemstring = deSerializeString(is);
}

updateNodePos();

/*
Set infotext to item name if item cannot be deserialized
*/
try{
InventoryItem *item = NULL;
item = InventoryItem::deSerialize(m_inventorystring, m_gamedef);
if(item){
if(!item->isKnown())
m_infotext = "Unknown item: '" + m_inventorystring + "'";
}
delete item;
}
catch(SerializationError &e)
{
m_infotext = "Unknown item: '" + m_inventorystring + "'";
}
updateInfoText();
}

/*
Expand Down
284 changes: 130 additions & 154 deletions src/content_mapblock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,112 +20,105 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "content_mapblock.h"

#include "main.h" // For g_settings
#include "mineral.h"
#include "mapblock_mesh.h" // For MapBlock_LightColor()
#include "mapblock_mesh.h" // For MapBlock_LightColor() and MeshCollector
#include "settings.h"
#include "nodedef.h"
#include "tile.h"
#include "gamedef.h"

#ifndef SERVER
// Create a cuboid.
// material - the material to use (for all 6 faces)
// collector - the MeshCollector for the resulting polygons
// pa - texture atlas pointer for the material
// box - the position and size of the box
// materials - the materials to use (for all 6 faces)
// pa - texture atlas pointers for the materials
// matcount - number of entries in "materials" and "pa", 1<=matcount<=6
// c - vertex colour - used for all
// pos - the position of the centre of the cuboid
// rz,ry,rz - the radius of the cuboid in each dimension
// txc - texture coordinates - this is a list of texture coordinates
// for the opposite corners of each face - therefore, there
// should be (2+2)*6=24 values in the list. Alternatively, pass
// NULL to use the entire texture for each face. The order of
// the faces in the list is top-backi-right-front-left-bottom
// If you specified 0,0,1,1 for each face, that would be the
// same as passing NULL.
void makeCuboid(video::SMaterial &material, MeshCollector *collector,
AtlasPointer* pa, video::SColor &c,
v3f &pos, f32 rx, f32 ry, f32 rz, f32* txc)
// the faces in the list is up-down-right-left-back-front
// (compatible with ContentFeatures). If you specified 0,0,1,1
// for each face, that would be the same as passing NULL.
void makeCuboid(MeshCollector *collector, const aabb3f &box,
const video::SMaterial *materials, const AtlasPointer *pa, int matcount,
video::SColor &c, const f32* txc)
{
f32 tu0=pa->x0();
f32 tu1=pa->x1();
f32 tv0=pa->y0();
f32 tv1=pa->y1();
f32 txus=tu1-tu0;
f32 txvs=tv1-tv0;

video::S3DVertex v[4] =
assert(matcount >= 1);

v3f min = box.MinEdge;
v3f max = box.MaxEdge;

if(txc == NULL)
{
video::S3DVertex(0,0,0, 0,0,0, c, tu0, tv1),
video::S3DVertex(0,0,0, 0,0,0, c, tu1, tv1),
video::S3DVertex(0,0,0, 0,0,0, c, tu1, tv0),
video::S3DVertex(0,0,0, 0,0,0, c, tu0, tv0)
};
static const f32 txc_default[24] = {
0,0,1,1,
0,0,1,1,
0,0,1,1,
0,0,1,1,
0,0,1,1,
0,0,1,1
};
txc = txc_default;
}

for(int i=0;i<6;i++)
video::S3DVertex vertices[24] =
{
switch(i)
{
case 0: // top
v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
v[2].Pos.X= rx; v[2].Pos.Y= ry; v[2].Pos.Z= rz;
v[3].Pos.X= rx; v[3].Pos.Y= ry, v[3].Pos.Z=-rz;
break;
case 1: // back
v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
v[1].Pos.X= rx; v[1].Pos.Y= ry; v[1].Pos.Z=-rz;
v[2].Pos.X= rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
v[3].Pos.X=-rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
break;
case 2: //right
v[0].Pos.X= rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
v[1].Pos.X= rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
v[2].Pos.X= rx; v[2].Pos.Y=-ry; v[2].Pos.Z= rz;
v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
break;
case 3: // front
v[0].Pos.X= rx; v[0].Pos.Y= ry; v[0].Pos.Z= rz;
v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z= rz;
v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z= rz;
break;
case 4: // left
v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z= rz;
v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z=-rz;
v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
v[3].Pos.X=-rx; v[3].Pos.Y=-ry, v[3].Pos.Z= rz;
break;
case 5: // bottom
v[0].Pos.X= rx; v[0].Pos.Y=-ry; v[0].Pos.Z= rz;
v[1].Pos.X=-rx; v[1].Pos.Y=-ry; v[1].Pos.Z= rz;
v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
break;
}
// up
video::S3DVertex(min.X,max.Y,max.Z, 0,1,0, c, txc[0],txc[1]),
video::S3DVertex(max.X,max.Y,max.Z, 0,1,0, c, txc[2],txc[1]),
video::S3DVertex(max.X,max.Y,min.Z, 0,1,0, c, txc[2],txc[3]),
video::S3DVertex(min.X,max.Y,min.Z, 0,1,0, c, txc[0],txc[3]),
// down
video::S3DVertex(min.X,min.Y,min.Z, 0,-1,0, c, txc[4],txc[5]),
video::S3DVertex(max.X,min.Y,min.Z, 0,-1,0, c, txc[6],txc[5]),
video::S3DVertex(max.X,min.Y,max.Z, 0,-1,0, c, txc[6],txc[7]),
video::S3DVertex(min.X,min.Y,max.Z, 0,-1,0, c, txc[4],txc[7]),
// right
video::S3DVertex(max.X,max.Y,min.Z, 1,0,0, c, txc[ 8],txc[9]),
video::S3DVertex(max.X,max.Y,max.Z, 1,0,0, c, txc[10],txc[9]),
video::S3DVertex(max.X,min.Y,max.Z, 1,0,0, c, txc[10],txc[11]),
video::S3DVertex(max.X,min.Y,min.Z, 1,0,0, c, txc[ 8],txc[11]),
// left
video::S3DVertex(min.X,max.Y,max.Z, -1,0,0, c, txc[12],txc[13]),
video::S3DVertex(min.X,max.Y,min.Z, -1,0,0, c, txc[14],txc[13]),
video::S3DVertex(min.X,min.Y,min.Z, -1,0,0, c, txc[14],txc[15]),
video::S3DVertex(min.X,min.Y,max.Z, -1,0,0, c, txc[12],txc[15]),
// back
video::S3DVertex(min.X,max.Y,min.Z, 0,0,-1, c, txc[16],txc[17]),
video::S3DVertex(max.X,max.Y,min.Z, 0,0,-1, c, txc[18],txc[17]),
video::S3DVertex(max.X,min.Y,min.Z, 0,0,-1, c, txc[18],txc[19]),
video::S3DVertex(min.X,min.Y,min.Z, 0,0,-1, c, txc[16],txc[19]),
// front
video::S3DVertex(max.X,max.Y,max.Z, 0,0,1, c, txc[20],txc[21]),
video::S3DVertex(min.X,max.Y,max.Z, 0,0,1, c, txc[22],txc[21]),
video::S3DVertex(min.X,min.Y,max.Z, 0,0,1, c, txc[22],txc[23]),
video::S3DVertex(max.X,min.Y,max.Z, 0,0,1, c, txc[20],txc[23]),
};

if(txc!=NULL)
{
v[0].TCoords.X=tu0+txus*txc[0]; v[0].TCoords.Y=tv0+txvs*txc[3];
v[1].TCoords.X=tu0+txus*txc[2]; v[1].TCoords.Y=tv0+txvs*txc[3];
v[2].TCoords.X=tu0+txus*txc[2]; v[2].TCoords.Y=tv0+txvs*txc[1];
v[3].TCoords.X=tu0+txus*txc[0]; v[3].TCoords.Y=tv0+txvs*txc[1];
txc+=4;
}
for(s32 j=0; j<24; j++)
{
int matindex = MYMIN(j/4, matcount-1);
vertices[j].TCoords *= pa[matindex].size;
vertices[j].TCoords += pa[matindex].pos;
}

for(u16 i=0; i<4; i++)
v[i].Pos += pos;
u16 indices[] = {0,1,2,2,3,0};
collector->append(material, v, 4, indices, 6);
u16 indices[] = {0,1,2,2,3,0};

// Add to mesh collector
for(s32 j=0; j<24; j+=4)
{
int matindex = MYMIN(j/4, matcount-1);
collector->append(materials[matindex],
vertices+j, 4, indices, 6);
}

}
#endif

#ifndef SERVER
void mapblock_mesh_generate_special(MeshMakeData *data,
MeshCollector &collector, IGameDef *gamedef)
{
INodeDefManager *nodedef = gamedef->ndef();
ITextureSource *tsrc = gamedef->getTextureSource();

// 0ms
//TimeTaker timer("mapblock_mesh_generate_special()");
Expand Down Expand Up @@ -521,7 +514,9 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
material_glass.setFlag(video::EMF_BILINEAR_FILTER, false);
material_glass.setFlag(video::EMF_FOG_ENABLE, true);
material_glass.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
AtlasPointer pa_glass = f.tiles[0].texture;
TileSpec tile_glass = getNodeTile(n, p, v3s16(0,0,0),
&data->m_temp_mods, tsrc, nodedef);
AtlasPointer pa_glass = tile_glass.texture;
material_glass.setTexture(0, pa_glass.atlas);

u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio, nodedef)));
Expand Down Expand Up @@ -585,54 +580,21 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
material_leaves1.setFlag(video::EMF_BILINEAR_FILTER, false);
material_leaves1.setFlag(video::EMF_FOG_ENABLE, true);
material_leaves1.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
AtlasPointer pa_leaves1 = f.tiles[0].texture;
TileSpec tile_leaves1 = getNodeTile(n, p, v3s16(0,0,0),
&data->m_temp_mods, tsrc, nodedef);
AtlasPointer pa_leaves1 = tile_leaves1.texture;
material_leaves1.setTexture(0, pa_leaves1.atlas);

u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio, nodedef)));
video::SColor c = MapBlock_LightColor(255, l);

for(u32 j=0; j<6; j++)
{
video::S3DVertex vertices[4] =
{
video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c,
pa_leaves1.x0(), pa_leaves1.y1()),
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c,
pa_leaves1.x1(), pa_leaves1.y1()),
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c,
pa_leaves1.x1(), pa_leaves1.y0()),
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c,
pa_leaves1.x0(), pa_leaves1.y0()),
};

// Rotations in the g_6dirs format
if(j == 0) // Z+
for(u16 i=0; i<4; i++)
vertices[i].Pos.rotateXZBy(0);
else if(j == 1) // Y+
for(u16 i=0; i<4; i++)
vertices[i].Pos.rotateYZBy(-90);
else if(j == 2) // X+
for(u16 i=0; i<4; i++)
vertices[i].Pos.rotateXZBy(-90);
else if(j == 3) // Z-
for(u16 i=0; i<4; i++)
vertices[i].Pos.rotateXZBy(180);
else if(j == 4) // Y-
for(u16 i=0; i<4; i++)
vertices[i].Pos.rotateYZBy(90);
else if(j == 5) // X-
for(u16 i=0; i<4; i++)
vertices[i].Pos.rotateXZBy(90);

for(u16 i=0; i<4; i++){
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
}

u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector
collector.append(material_leaves1, vertices, 4, indices, 6);
}
v3f pos = intToFloat(p+blockpos_nodes, BS);
aabb3f box(-BS/2,-BS/2,-BS/2,BS/2,BS/2,BS/2);
box.MinEdge += pos;
box.MaxEdge += pos;
makeCuboid(&collector, box,
&material_leaves1, &pa_leaves1, 1,
c, NULL);
break;}
case NDT_ALLFACES_OPTIONAL:
// This is always pre-converted to something else
Expand Down Expand Up @@ -824,28 +786,44 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
material_wood.setFlag(video::EMF_BILINEAR_FILTER, false);
material_wood.setFlag(video::EMF_FOG_ENABLE, true);
material_wood.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
AtlasPointer pa_wood = f.tiles[0].texture;
TileSpec tile_wood = getNodeTile(n, p, v3s16(0,0,0),
&data->m_temp_mods, tsrc, nodedef);
AtlasPointer pa_wood = tile_wood.texture;
material_wood.setTexture(0, pa_wood.atlas);

video::SMaterial material_wood_nomod;
material_wood_nomod.setFlag(video::EMF_LIGHTING, false);
material_wood_nomod.setFlag(video::EMF_BILINEAR_FILTER, false);
material_wood_nomod.setFlag(video::EMF_FOG_ENABLE, true);
material_wood_nomod.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;

TileSpec tile_wood_nomod = getNodeTile(n, p, v3s16(0,0,0),
NULL, tsrc, nodedef);
AtlasPointer pa_wood_nomod = tile_wood_nomod.texture;
material_wood_nomod.setTexture(0, pa_wood_nomod.atlas);

u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio, nodedef)));
video::SColor c = MapBlock_LightColor(255, l);

const f32 post_rad=(f32)BS/10;
const f32 bar_rad=(f32)BS/20;
const f32 bar_len=(f32)(BS/2)-post_rad;

// The post - always present
v3f pos = intToFloat(p+blockpos_nodes, BS);

// The post - always present
aabb3f post(-post_rad,-BS/2,-post_rad,post_rad,BS/2,post_rad);
post.MinEdge += pos;
post.MaxEdge += pos;
f32 postuv[24]={
0.4,0.4,0.6,0.6,
0.4,0.4,0.6,0.6,
0.35,0,0.65,1,
0.35,0,0.65,1,
0.35,0,0.65,1,
0.35,0,0.65,1,
0.4,0.4,0.6,0.6};
makeCuboid(material_wood, &collector,
&pa_wood, c, pos,
post_rad,BS/2,post_rad, postuv);
0.35,0,0.65,1};
makeCuboid(&collector, post, &material_wood,
&pa_wood, 1, c, postuv);

// Now a section of fence, +X, if there's a post there
v3s16 p2 = p;
Expand All @@ -854,24 +832,23 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
const ContentFeatures *f2 = &nodedef->get(n2);
if(f2->drawtype == NDT_FENCELIKE)
{
pos = intToFloat(p+blockpos_nodes, BS);
pos.X += BS/2;
pos.Y += BS/4;
aabb3f bar(-bar_len+BS/2,-bar_rad+BS/4,-bar_rad,
bar_len+BS/2,bar_rad+BS/4,bar_rad);
bar.MinEdge += pos;
bar.MaxEdge += pos;
f32 xrailuv[24]={
0,0.4,1,0.6,
0,0.4,1,0.6,
0,0.4,1,0.6,
0,0.4,1,0.6,
0,0.4,1,0.6,
0,0.4,1,0.6};
makeCuboid(material_wood, &collector,
&pa_wood, c, pos,
bar_len,bar_rad,bar_rad, xrailuv);

pos.Y -= BS/2;
makeCuboid(material_wood, &collector,
&pa_wood, c, pos,
bar_len,bar_rad,bar_rad, xrailuv);
makeCuboid(&collector, bar, &material_wood_nomod,
&pa_wood_nomod, 1, c, xrailuv);
bar.MinEdge.Y -= BS/2;
bar.MaxEdge.Y -= BS/2;
makeCuboid(&collector, bar, &material_wood_nomod,
&pa_wood_nomod, 1, c, xrailuv);
}

// Now a section of fence, +Z, if there's a post there
Expand All @@ -881,24 +858,24 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
f2 = &nodedef->get(n2);
if(f2->drawtype == NDT_FENCELIKE)
{
pos = intToFloat(p+blockpos_nodes, BS);
pos.Z += BS/2;
pos.Y += BS/4;
aabb3f bar(-bar_rad,-bar_rad+BS/4,-bar_len+BS/2,
bar_rad,bar_rad+BS/4,bar_len+BS/2);
bar.MinEdge += pos;
bar.MaxEdge += pos;
f32 zrailuv[24]={
0,0.4,1,0.6,
0,0.4,1,0.6,
0,0.4,1,0.6,
0,0.4,1,0.6,
0,0.4,1,0.6,
0,0.4,1,0.6};
makeCuboid(material_wood, &collector,
&pa_wood, c, pos,
bar_rad,bar_rad,bar_len, zrailuv);
pos.Y -= BS/2;
makeCuboid(material_wood, &collector,
&pa_wood, c, pos,
bar_rad,bar_rad,bar_len, zrailuv);

makeCuboid(&collector, bar, &material_wood_nomod,
&pa_wood_nomod, 1, c, zrailuv);
bar.MinEdge.Y -= BS/2;
bar.MaxEdge.Y -= BS/2;
makeCuboid(&collector, bar, &material_wood_nomod,
&pa_wood_nomod, 1, c, zrailuv);
}
break;}
case NDT_RAILLIKE:
Expand Down Expand Up @@ -1011,5 +988,4 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
}
}
}
#endif

831 changes: 80 additions & 751 deletions src/content_mapnode.cpp

Large diffs are not rendered by default.

6 changes: 0 additions & 6 deletions src/content_mapnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Legacy node definitions
*/

class IWritableNodeDefManager;

// Initialize legacy node definitions
// Not used used anywhere else than in test.cpp (and SHALL NOT BE)
void content_mapnode_init(IWritableNodeDefManager *nodemgr);

// Backwards compatibility for non-extended content types in v19
extern content_t trans_table_19[21][2];
MapNode mapnode_translate_from_internal(MapNode n_from, u8 version);
Expand Down
287 changes: 179 additions & 108 deletions src/content_nodemeta.cpp

Large diffs are not rendered by default.

154 changes: 96 additions & 58 deletions src/content_sao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "main.h" // For g_profiler
#include "profiler.h"
#include "serialization.h" // For compressZlib
#include "materials.h" // For MaterialProperties
#include "tooldef.h" // ToolDiggingProperties
#include "materials.h" // For MaterialProperties and ToolDiggingProperties
#include "gamedef.h"

core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;

Expand Down Expand Up @@ -114,9 +114,10 @@ void TestSAO::step(float dtime, bool send_recommended)
ItemSAO proto_ItemSAO(NULL, v3f(0,0,0), "");

ItemSAO::ItemSAO(ServerEnvironment *env, v3f pos,
const std::string inventorystring):
const std::string itemstring):
ServerActiveObject(env, pos),
m_inventorystring(inventorystring),
m_itemstring(itemstring),
m_itemstring_changed(false),
m_speed_f(0,0,0),
m_last_sent_position(0,0,0)
{
Expand All @@ -134,10 +135,10 @@ ServerActiveObject* ItemSAO::create(ServerEnvironment *env, v3f pos,
// check if version is supported
if(version != 0)
return NULL;
std::string inventorystring = deSerializeString(is);
std::string itemstring = deSerializeString(is);
infostream<<"ItemSAO::create(): Creating item \""
<<inventorystring<<"\""<<std::endl;
return new ItemSAO(env, pos, inventorystring);
<<itemstring<<"\""<<std::endl;
return new ItemSAO(env, pos, itemstring);
}

void ItemSAO::step(float dtime, bool send_recommended)
Expand Down Expand Up @@ -175,17 +176,23 @@ void ItemSAO::step(float dtime, bool send_recommended)
m_last_sent_position = pos_f;

std::ostringstream os(std::ios::binary);
char buf[6];
// command (0 = update position)
buf[0] = 0;
os.write(buf, 1);
writeU8(os, 0);
// pos
writeS32((u8*)buf, m_base_position.X*1000);
os.write(buf, 4);
writeS32((u8*)buf, m_base_position.Y*1000);
os.write(buf, 4);
writeS32((u8*)buf, m_base_position.Z*1000);
os.write(buf, 4);
writeV3F1000(os, m_base_position);
// create message and add to list
ActiveObjectMessage aom(getId(), false, os.str());
m_messages_out.push_back(aom);
}
if(m_itemstring_changed)
{
m_itemstring_changed = false;

std::ostringstream os(std::ios::binary);
// command (1 = update itemstring)
writeU8(os, 1);
// itemstring
os<<serializeString(m_itemstring);
// create message and add to list
ActiveObjectMessage aom(getId(), false, os.str());
m_messages_out.push_back(aom);
Expand All @@ -195,62 +202,71 @@ void ItemSAO::step(float dtime, bool send_recommended)
std::string ItemSAO::getClientInitializationData()
{
std::ostringstream os(std::ios::binary);
char buf[6];
// version
buf[0] = 0;
os.write(buf, 1);
writeU8(os, 0);
// pos
writeS32((u8*)buf, m_base_position.X*1000);
os.write(buf, 4);
writeS32((u8*)buf, m_base_position.Y*1000);
os.write(buf, 4);
writeS32((u8*)buf, m_base_position.Z*1000);
os.write(buf, 4);
// inventorystring
os<<serializeString(m_inventorystring);
writeV3F1000(os, m_base_position);
// itemstring
os<<serializeString(m_itemstring);
return os.str();
}

std::string ItemSAO::getStaticData()
{
infostream<<__FUNCTION_NAME<<std::endl;
std::ostringstream os(std::ios::binary);
char buf[1];
// version
buf[0] = 0;
os.write(buf, 1);
// inventorystring
os<<serializeString(m_inventorystring);
writeU8(os, 0);
// itemstring
os<<serializeString(m_itemstring);
return os.str();
}

InventoryItem * ItemSAO::createInventoryItem()
ItemStack ItemSAO::createItemStack()
{
try{
std::istringstream is(m_inventorystring, std::ios_base::binary);
IGameDef *gamedef = m_env->getGameDef();
InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
<<m_inventorystring<<"\" -> item="<<item
IItemDefManager *idef = m_env->getGameDef()->idef();
ItemStack item;
item.deSerialize(m_itemstring, idef);
infostream<<__FUNCTION_NAME<<": m_itemstring=\""<<m_itemstring
<<"\" -> item=\""<<item.getItemString()<<"\""
<<std::endl;
return item;
}
catch(SerializationError &e)
{
infostream<<__FUNCTION_NAME<<": serialization error: "
<<"m_inventorystring=\""<<m_inventorystring<<"\""<<std::endl;
return NULL;
<<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl;
return ItemStack();
}
}

void ItemSAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
{
InventoryItem *item = createInventoryItem();
bool fits = puncher->addToInventory(item);
if(fits)
// Allow removing items in creative mode
if(g_settings->getBool("creative_mode") == true)
{
m_removed = true;
else
delete item;
return;
}

ItemStack item = createItemStack();
Inventory *inv = puncher->getInventory();
if(inv != NULL)
{
std::string wieldlist = puncher->getWieldList();
ItemStack leftover = inv->addItem(wieldlist, item);
puncher->setInventoryModified();
if(leftover.empty())
{
m_removed = true;
}
else
{
m_itemstring = leftover.getItemString();
m_itemstring_changed = true;
}
}
}

/*
Expand Down Expand Up @@ -436,14 +452,24 @@ std::string RatSAO::getStaticData()

void RatSAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
{
std::istringstream is("CraftItem rat 1", std::ios_base::binary);
IGameDef *gamedef = m_env->getGameDef();
InventoryItem *item = InventoryItem::deSerialize(is, gamedef);
bool fits = puncher->addToInventory(item);
if(fits)
// Allow removing rats in creative mode
if(g_settings->getBool("creative_mode") == true)
{
m_removed = true;
else
delete item;
return;
}

IItemDefManager *idef = m_env->getGameDef()->idef();
ItemStack item("rat", 1, 0, "", idef);
Inventory *inv = puncher->getInventory();
if(inv != NULL)
{
std::string wieldlist = puncher->getWieldList();
ItemStack leftover = inv->addItem(wieldlist, item);
puncher->setInventoryModified();
if(leftover.empty())
m_removed = true;
}
}

/*
Expand Down Expand Up @@ -703,14 +729,20 @@ void Oerkki1SAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
mp.crackiness = -1.0;
mp.cuttability = 1.0;

ToolDiggingProperties tp;
puncher->getWieldDiggingProperties(&tp);
IItemDefManager *idef = m_env->getGameDef()->idef();
ItemStack punchitem = puncher->getWieldedItem();
ToolDiggingProperties tp =
punchitem.getToolDiggingProperties(idef);

HittingProperties hitprop = getHittingProperties(&mp, &tp,
time_from_last_punch);

doDamage(hitprop.hp);
puncher->damageWieldedItem(hitprop.wear);
if(g_settings->getBool("creative_mode") == false)
{
punchitem.addWear(hitprop.wear, idef);
puncher->setWieldedItem(punchitem);
}
}

void Oerkki1SAO::doDamage(u16 d)
Expand Down Expand Up @@ -1393,14 +1425,20 @@ void MobV2SAO::punch(ServerActiveObject *puncher, float time_from_last_punch)
mp.crackiness = -1.0;
mp.cuttability = 1.0;

ToolDiggingProperties tp;
puncher->getWieldDiggingProperties(&tp);
IItemDefManager *idef = m_env->getGameDef()->idef();
ItemStack punchitem = puncher->getWieldedItem();
ToolDiggingProperties tp =
punchitem.getToolDiggingProperties(idef);

HittingProperties hitprop = getHittingProperties(&mp, &tp,
time_from_last_punch);

doDamage(hitprop.hp);
puncher->damageWieldedItem(hitprop.wear);
if(g_settings->getBool("creative_mode") == false)
{
punchitem.addWear(hitprop.wear, idef);
puncher->setWieldedItem(punchitem);
}
}

bool MobV2SAO::isPeaceful()
Expand Down
8 changes: 4 additions & 4 deletions src/content_sao.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,20 @@ class TestSAO : public ServerActiveObject
class ItemSAO : public ServerActiveObject
{
public:
ItemSAO(ServerEnvironment *env, v3f pos,
const std::string inventorystring);
ItemSAO(ServerEnvironment *env, v3f pos, const std::string itemstring);
u8 getType() const
{return ACTIVEOBJECT_TYPE_ITEM;}
static ServerActiveObject* create(ServerEnvironment *env, v3f pos,
const std::string &data);
void step(float dtime, bool send_recommended);
std::string getClientInitializationData();
std::string getStaticData();
InventoryItem* createInventoryItem();
ItemStack createItemStack();
void punch(ServerActiveObject *puncher, float time_from_last_punch);
float getMinimumSavedMovement(){ return 0.1*BS; }
private:
std::string m_inventorystring;
std::string m_itemstring;
bool m_itemstring_changed;
v3f m_speed_f;
v3f m_last_sent_position;
IntervalLimiter m_move_interval;
Expand Down
844 changes: 744 additions & 100 deletions src/craftdef.cpp

Large diffs are not rendered by default.

349 changes: 307 additions & 42 deletions src/craftdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,85 +23,350 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <string>
#include <iostream>
#include <vector>
class IGameDef;
class InventoryItem;
#include <utility>
#include "gamedef.h"
#include "inventory.h"

struct CraftPointerInput
/*
Crafting methods.
The crafting method depends on the inventory list
that the crafting input comes from.
*/
enum CraftMethod
{
// Crafting grid
CRAFT_METHOD_NORMAL,
// Cooking something in a furnace
CRAFT_METHOD_COOKING,
// Using something as fuel for a furnace
CRAFT_METHOD_FUEL,
};

/*
Input: The contents of the crafting slots, arranged in matrix form
*/
struct CraftInput
{
CraftMethod method;
unsigned int width;
std::vector<InventoryItem*> items;
std::vector<ItemStack> items;

CraftPointerInput(unsigned int width_, const std::vector<InventoryItem*> &items_):
width(width_),
items(items_)
CraftInput():
method(CRAFT_METHOD_NORMAL), width(0), items()
{}
CraftPointerInput():
width(0)
CraftInput(CraftMethod method_, unsigned int width_,
const std::vector<ItemStack> &items_):
method(method_), width(width_), items(items_)
{}
~CraftPointerInput();
unsigned int height() const{
return (items.size() + width - 1) / width;
}
std::string dump() const;
};

struct CraftInput
/*
Output: Result of crafting operation
*/
struct CraftOutput
{
unsigned int width;
std::vector<std::string> items;
// Used for normal crafting and cooking, itemstring
std::string item;
// Used for cooking (cook time) and fuel (burn time), seconds
float time;

CraftInput(unsigned int width_, const std::vector<std::string> &items_):
width(width_),
items(items_)
CraftOutput():
item(""), time(0)
{}
CraftInput():
width(0)
CraftOutput(std::string item_, float time_):
item(item_), time(time_)
{}
unsigned int height() const{
return (items.size() + width - 1) / width;
}
std::string dump() const;
};

struct CraftDefinition
/*
A list of replacements. A replacement indicates that a specific
input item should not be deleted (when crafting) but replaced with
a different item. Each replacements is a pair (itemstring to remove,
itemstring to replace with)
Example: If ("bucket:bucket_water", "bucket:bucket_empty") is a
replacement pair, the crafting input slot that contained a water
bucket will contain an empty bucket after crafting.
Note: replacements only work correctly when stack_max of the item
to be replaced is 1. It is up to the mod writer to ensure this.
*/
struct CraftReplacements
{
std::string output;
CraftInput input;
// List of replacements
std::vector<std::pair<std::string, std::string> > pairs;

CraftDefinition(){}
CraftDefinition(const std::string &output_, unsigned int width_,
const std::vector<std::string> &input_):
output(output_),
input(width_, input_)
CraftReplacements():
pairs()
{}
CraftReplacements(std::vector<std::pair<std::string, std::string> > pairs_):
pairs(pairs_)
{}

std::string dump() const;
};

/*
Crafting definition base class
*/
class CraftDefinition
{
public:
CraftDefinition(){}
virtual ~CraftDefinition(){}

void serialize(std::ostream &os) const;
void deSerialize(std::istream &is);
static CraftDefinition* deSerialize(std::istream &is);

// Returns type of crafting definition
virtual std::string getName() const=0;

// Checks whether the recipe is applicable
virtual bool check(const CraftInput &input, IGameDef *gamedef) const=0;
// Returns the output structure, meaning depends on crafting method
// The implementation can assume that check(input) returns true
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const=0;
// Decreases count of every input item
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const=0;

virtual std::string dump() const=0;

protected:
virtual void serializeBody(std::ostream &os) const=0;
virtual void deSerializeBody(std::istream &is, int version)=0;
};

/*
A plain-jane (shaped) crafting definition
Supported crafting method: CRAFT_METHOD_NORMAL.
Requires the input items to be arranged exactly like in the recipe.
*/
class CraftDefinitionShaped: public CraftDefinition
{
public:
CraftDefinitionShaped():
output(""), width(1), recipe(), replacements()
{}
CraftDefinitionShaped(
const std::string &output_,
unsigned int width_,
const std::vector<std::string> &recipe_,
const CraftReplacements &replacements_):
output(output_), width(width_), recipe(recipe_), replacements(replacements_)
{}
virtual ~CraftDefinitionShaped(){}

virtual std::string getName() const;
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;

virtual std::string dump() const;

protected:
virtual void serializeBody(std::ostream &os) const;
virtual void deSerializeBody(std::istream &is, int version);

private:
// Output itemstring
std::string output;
// Width of recipe
unsigned int width;
// Recipe matrix (itemstrings)
std::vector<std::string> recipe;
// Replacement items for decrementInput()
CraftReplacements replacements;
};

/*
A shapeless crafting definition
Supported crafting method: CRAFT_METHOD_NORMAL.
Input items can arranged in any way.
*/
class CraftDefinitionShapeless: public CraftDefinition
{
public:
CraftDefinitionShapeless():
output(""), recipe(), replacements()
{}
CraftDefinitionShapeless(
const std::string &output_,
const std::vector<std::string> &recipe_,
const CraftReplacements &replacements_):
output(output_), recipe(recipe_), replacements(replacements_)
{}
virtual ~CraftDefinitionShapeless(){}

virtual std::string getName() const;
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;

virtual std::string dump() const;

protected:
virtual void serializeBody(std::ostream &os) const;
virtual void deSerializeBody(std::istream &is, int version);

private:
// Output itemstring
std::string output;
// Recipe list (itemstrings)
std::vector<std::string> recipe;
// Replacement items for decrementInput()
CraftReplacements replacements;
};

/*
Tool repair crafting definition
Supported crafting method: CRAFT_METHOD_NORMAL.
Put two damaged tools into the crafting grid, get one tool back.
There should only be one crafting definition of this type.
*/
class CraftDefinitionToolRepair: public CraftDefinition
{
public:
CraftDefinitionToolRepair():
additional_wear(0)
{}
CraftDefinitionToolRepair(float additional_wear_):
additional_wear(additional_wear_)
{}
virtual ~CraftDefinitionToolRepair(){}

virtual std::string getName() const;
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;

virtual std::string dump() const;

protected:
virtual void serializeBody(std::ostream &os) const;
virtual void deSerializeBody(std::istream &is, int version);

private:
// This is a constant that is added to the wear of the result.
// May be positive or negative, allowed range [-1,1].
// 1 = new tool is completely broken
// 0 = simply add remaining uses of both input tools
// -1 = new tool is completely pristine
float additional_wear;
};

/*
A cooking (in furnace) definition
Supported crafting method: CRAFT_METHOD_COOKING.
*/
class CraftDefinitionCooking: public CraftDefinition
{
public:
CraftDefinitionCooking():
output(""), recipe(""), cooktime()
{}
CraftDefinitionCooking(
const std::string &output_,
const std::string &recipe_,
float cooktime_):
output(output_), recipe(recipe_), cooktime(cooktime_)
{}
virtual ~CraftDefinitionCooking(){}

virtual std::string getName() const;
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;

virtual std::string dump() const;

protected:
virtual void serializeBody(std::ostream &os) const;
virtual void deSerializeBody(std::istream &is, int version);

private:
// Output itemstring
std::string output;
// Recipe itemstring
std::string recipe;
// Time in seconds
float cooktime;
};

/*
A fuel (for furnace) definition
Supported crafting method: CRAFT_METHOD_FUEL.
*/
class CraftDefinitionFuel: public CraftDefinition
{
public:
CraftDefinitionFuel():
recipe(""), burntime()
{}
CraftDefinitionFuel(std::string recipe_, float burntime_):
recipe(recipe_), burntime(burntime_)
{}
virtual ~CraftDefinitionFuel(){}

virtual std::string getName() const;
virtual bool check(const CraftInput &input, IGameDef *gamedef) const;
virtual CraftOutput getOutput(const CraftInput &input, IGameDef *gamedef) const;
virtual void decrementInput(CraftInput &input, IGameDef *gamedef) const;

virtual std::string dump() const;

protected:
virtual void serializeBody(std::ostream &os) const;
virtual void deSerializeBody(std::istream &is, int version);

private:
// Recipe itemstring
std::string recipe;
// Time in seconds
float burntime;
};

/*
Crafting definition manager
*/
class ICraftDefManager
{
public:
ICraftDefManager(){}
virtual ~ICraftDefManager(){}
virtual InventoryItem* getCraftResult(const CraftPointerInput &input_cpi,
IGameDef *gamedef) const=0;

// The main crafting function
virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
bool decrementInput, IGameDef *gamedef) const=0;

virtual void serialize(std::ostream &os)=0;
// Print crafting recipes for debugging
virtual std::string dump() const=0;

virtual void serialize(std::ostream &os) const=0;
};

class IWritableCraftDefManager : public ICraftDefManager
{
public:
IWritableCraftDefManager(){}
virtual ~IWritableCraftDefManager(){}
virtual InventoryItem* getCraftResult(const CraftPointerInput &input_cpi,
IGameDef *gamedef) const=0;

virtual void registerCraft(const CraftDefinition &def)=0;

// The main crafting function
virtual bool getCraftResult(CraftInput &input, CraftOutput &output,
bool decrementInput, IGameDef *gamedef) const=0;

// Print crafting recipes for debugging
virtual std::string dump() const=0;

// Add a crafting definition.
// After calling this, the pointer belongs to the manager.
virtual void registerCraft(CraftDefinition *def)=0;
// Delete all crafting definitions
virtual void clear()=0;

virtual void serialize(std::ostream &os)=0;
virtual void serialize(std::ostream &os) const=0;
virtual void deSerialize(std::istream &is)=0;
};

Expand Down
214 changes: 0 additions & 214 deletions src/craftitemdef.cpp

This file was deleted.

79 changes: 0 additions & 79 deletions src/craftitemdef.h

This file was deleted.

1 change: 1 addition & 0 deletions src/environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "activeobject.h"

class Server;
class ServerEnvironment;
class ActiveBlockModifier;
class ServerActiveObject;
typedef struct lua_State lua_State;
Expand Down
134 changes: 48 additions & 86 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "settings.h"
#include "profiler.h"
#include "mainmenumanager.h"
#include "craftitemdef.h"
#include "gettext.h"
#include "log.h"
#include "filesys.h"
// Needed for determining pointing to nodes
#include "nodedef.h"
#include "nodemetadata.h"
#include "main.h" // For g_settings
#include "tooldef.h"
#include "itemdef.h"
#include "tile.h" // For TextureSource
#include "logoutputbuffer.h"

Expand Down Expand Up @@ -79,15 +78,6 @@ struct ChatLine
std::wstring text;
};

/*
Inventory stuff
*/

// Inventory actions from the menu are buffered here before sending
Queue<InventoryAction*> inventory_action_queue;
// This is a copy of the inventory that the client's environment has
Inventory local_inventory;

/*
Text input system
*/
Expand Down Expand Up @@ -156,7 +146,7 @@ class MainRespawnInitiator: public IRespawnInitiator
Hotbar draw routine
*/
void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
ITextureSource *tsrc,
IGameDef *gamedef,
v2s32 centerlowerpos, s32 imgsize, s32 itemcount,
Inventory *inventory, s32 halfheartcount, u16 playeritem)
{
Expand Down Expand Up @@ -184,7 +174,7 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,

for(s32 i=0; i<itemcount; i++)
{
InventoryItem *item = mainlist->getItem(i);
const ItemStack &item = mainlist->getItem(i);

core::rect<s32> rect = imgrect + pos
+ v2s32(padding+i*(imgsize+padding*2), padding);
Expand Down Expand Up @@ -245,17 +235,14 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,

video::SColor bgcolor2(128,0,0,0);
driver->draw2DRectangle(bgcolor2, rect, NULL);

if(item != NULL)
{
drawInventoryItem(driver, font, item, rect, NULL, tsrc);
}
drawItemStack(driver, font, item, rect, NULL, gamedef);
}

/*
Draw hearts
*/
video::ITexture *heart_texture = tsrc->getTextureRaw("heart.png");
video::ITexture *heart_texture =
gamedef->getTextureSource()->getTextureRaw("heart.png");
if(heart_texture)
{
v2s32 p = pos + v2s32(0, -20);
Expand Down Expand Up @@ -691,12 +678,10 @@ void the_game(
IWritableTextureSource *tsrc = createTextureSource(device);

// These will be filled by data received from the server
// Create tool definition manager
IWritableToolDefManager *tooldef = createToolDefManager();
// Create item definition manager
IWritableItemDefManager *itemdef = createItemDefManager();
// Create node definition manager
IWritableNodeDefManager *nodedef = createNodeDefManager();
// Create CraftItem definition manager
IWritableCraftItemDefManager *craftitemdef = createCraftItemDefManager();

// Add chat log output for errors to be shown in chat
LogOutputBuffer chat_log_error_buf(LMT_ERROR);
Expand Down Expand Up @@ -725,7 +710,7 @@ void the_game(
MapDrawControl draw_control;

Client client(device, playername.c_str(), password, draw_control,
tsrc, tooldef, nodedef, craftitemdef);
tsrc, itemdef, nodedef);

// Client acts as our GameDef
IGameDef *gamedef = &client;
Expand Down Expand Up @@ -835,9 +820,8 @@ void the_game(

// End condition
if(client.texturesReceived() &&
client.tooldefReceived() &&
client.nodedefReceived() &&
client.craftitemdefReceived()){
client.itemdefReceived() &&
client.nodedefReceived()){
got_content = true;
break;
}
Expand All @@ -853,12 +837,10 @@ void the_game(
ss<<(int)(timeout - time_counter + 1.0);
ss<<L" seconds)\n";

ss<<(client.tooldefReceived()?L"[X]":L"[ ]");
ss<<L" Tool definitions\n";
ss<<(client.itemdefReceived()?L"[X]":L"[ ]");
ss<<L" Item definitions\n";
ss<<(client.nodedefReceived()?L"[X]":L"[ ]");
ss<<L" Node definitions\n";
ss<<(client.craftitemdefReceived()?L"[X]":L"[ ]");
ss<<L" Item definitions\n";
//ss<<(client.texturesReceived()?L"[X]":L"[ ]");
ss<<L"["<<(int)(client.textureReceiveProgress()*100+0.5)<<L"%] ";
ss<<L" Textures\n";
Expand All @@ -871,6 +853,12 @@ void the_game(
}
}

/*
After all content has been received:
Update cached textures, meshes and materials
*/
client.afterContentReceived();

/*
Create skybox
*/
Expand Down Expand Up @@ -910,6 +898,11 @@ void the_game(
farmesh = new FarMesh(smgr->getRootSceneNode(), smgr, -1, client.getMapSeed(), &client);
}

/*
A copy of the local inventory
*/
Inventory local_inventory(itemdef);

/*
Move into game
*/
Expand Down Expand Up @@ -1289,7 +1282,7 @@ void the_game(
// drop selected item
IDropAction *a = new IDropAction();
a->count = 0;
a->from_inv = "current_player";
a->from_inv.setCurrentPlayer();
a->from_list = "main";
a->from_i = client.getPlayerItem();
client.inventoryAction(a);
Expand All @@ -1302,18 +1295,20 @@ void the_game(
GUIInventoryMenu *menu =
new GUIInventoryMenu(guienv, guiroot, -1,
&g_menumgr, v2s16(8,7),
client.getInventoryContext(),
&client, tsrc);
&client, gamedef);

InventoryLocation inventoryloc;
inventoryloc.setCurrentPlayer();

core::array<GUIInventoryMenu::DrawSpec> draw_spec;
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
"list", "current_player", "main",
"list", inventoryloc, "main",
v2s32(0, 3), v2s32(8, 4)));
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
"list", "current_player", "craft",
"list", inventoryloc, "craft",
v2s32(3, 0), v2s32(3, 3)));
draw_spec.push_back(GUIInventoryMenu::DrawSpec(
"list", "current_player", "craftresult",
"list", inventoryloc, "craftresult",
v2s32(7, 1), v2s32(1, 1)));

menu->setDrawSpec(draw_spec);
Expand Down Expand Up @@ -1691,31 +1686,20 @@ void the_game(

/*
For interaction purposes, get info about the held item
- Is it a tool, and what is the toolname?
- What item is it?
- Is it a usable item?
- Can it point to liquids?
*/
std::string playeritem_toolname = "";
ItemStack playeritem;
bool playeritem_usable = false;
bool playeritem_liquids_pointable = false;
{
InventoryList *mlist = local_inventory.getList("main");
if(mlist != NULL)
{
InventoryItem *item = mlist->getItem(client.getPlayerItem());
if(item)
{
if((std::string)item->getName() == "ToolItem")
{
ToolItem *titem = (ToolItem*)item;
playeritem_toolname = titem->getToolName();
}

playeritem_usable = item->isUsable();

playeritem_liquids_pointable =
item->areLiquidsPointable();
}
playeritem = mlist->getItem(client.getPlayerItem());
playeritem_usable = playeritem.getDefinition(itemdef).usable;
playeritem_liquids_pointable = playeritem.getDefinition(itemdef).liquids_pointable;
}
}

Expand Down Expand Up @@ -1845,17 +1829,14 @@ void the_game(
// Get digging properties for material and tool
content_t material = n.getContent();
ToolDiggingProperties tp =
tooldef->getDiggingProperties(playeritem_toolname);
playeritem.getToolDiggingProperties(itemdef);
DiggingProperties prop =
getDiggingProperties(material, &tp, nodedef);

float dig_time_complete = 0.0;

if(prop.diggable == false)
{
/*infostream<<"Material "<<(int)material
<<" not diggable with \""
<<playeritem_toolname<<"\""<<std::endl;*/
// I guess nobody will wait for this long
dig_time_complete = 10000000.0;
}
Expand Down Expand Up @@ -1922,17 +1903,11 @@ void the_game(
if(meta && meta->getInventoryDrawSpecString() != "" && !random_input)
{
infostream<<"Launching custom inventory view"<<std::endl;
/*
Construct the unique identification string of the node
*/
std::string current_name;
current_name += "nodemeta:";
current_name += itos(nodepos.X);
current_name += ",";
current_name += itos(nodepos.Y);
current_name += ",";
current_name += itos(nodepos.Z);

InventoryLocation inventoryloc;
inventoryloc.setNodeMeta(nodepos);


/*
Create menu
*/
Expand All @@ -1942,13 +1917,12 @@ void the_game(
GUIInventoryMenu::makeDrawSpecArrayFromString(
draw_spec,
meta->getInventoryDrawSpecString(),
current_name);
inventoryloc);

GUIInventoryMenu *menu =
new GUIInventoryMenu(guienv, guiroot, -1,
&g_menumgr, invsize,
client.getInventoryContext(),
&client, tsrc);
&client, gamedef);
menu->setDrawSpec(draw_spec);
menu->drop();
}
Expand Down Expand Up @@ -2001,7 +1975,7 @@ void the_game(
v3f objpos = selected_object->getPosition();
v3f dir = (objpos - player_position).normalize();

bool disable_send = selected_object->directReportPunch(playeritem_toolname, dir);
bool disable_send = selected_object->directReportPunch(playeritem.name, dir);
if(!disable_send)
client.interact(0, pointed);
}
Expand Down Expand Up @@ -2285,24 +2259,12 @@ void the_game(
update_wielded_item_trigger = false;
// Update wielded tool
InventoryList *mlist = local_inventory.getList("main");
InventoryItem *item = NULL;
ItemStack item;
if(mlist != NULL)
item = mlist->getItem(client.getPlayerItem());
camera.wield(item, gamedef);
}

/*
Send actions returned by the inventory menu
*/
while(inventory_action_queue.size() != 0)
{
InventoryAction *a = inventory_action_queue.pop_front();

client.sendInventoryAction(a);
// Eat it
delete a;
}

/*
Drawing begins
*/
Expand Down Expand Up @@ -2411,7 +2373,7 @@ void the_game(
Draw hotbar
*/
{
draw_hotbar(driver, font, tsrc,
draw_hotbar(driver, font, gamedef,
v2s32(displaycenter.X, screensize.Y),
hotbar_imagesize, hotbar_itemcount, &local_inventory,
client.getHP(), client.getPlayerItem());
Expand Down Expand Up @@ -2482,9 +2444,9 @@ void the_game(

} // Client scope (must be destructed before destructing *def and tsrc

delete tooldef;
delete tsrc;
delete nodedef;
delete itemdef;
}


10 changes: 4 additions & 6 deletions src/gamedef.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define GAMEDEF_HEADER

#include <string>
#include "irrlichttypes.h"

class IToolDefManager;
class IItemDefManager;
class INodeDefManager;
class ICraftDefManager;
class ICraftItemDefManager;
// Mineral too?
class ITextureSource;

Expand All @@ -39,10 +39,9 @@ class IGameDef
public:
// These are thread-safe IF they are not edited while running threads.
// Thus, first they are set up and then they are only read.
virtual IToolDefManager* getToolDefManager()=0;
virtual IItemDefManager* getItemDefManager()=0;
virtual INodeDefManager* getNodeDefManager()=0;
virtual ICraftDefManager* getCraftDefManager()=0;
virtual ICraftItemDefManager* getCraftItemDefManager()=0;

// This is always thread-safe, but referencing the irrlicht texture
// pointers in other threads than main thread will make things explode.
Expand All @@ -52,10 +51,9 @@ class IGameDef
virtual u16 allocateUnknownNodeId(const std::string &name)=0;

// Shorthands
IToolDefManager* tdef(){return getToolDefManager();}
IItemDefManager* idef(){return getItemDefManager();}
INodeDefManager* ndef(){return getNodeDefManager();}
ICraftDefManager* cdef(){return getCraftDefManager();}
ICraftItemDefManager* cidef(){return getCraftItemDefManager();}
ITextureSource* tsrc(){return getTextureSource();}
};

Expand Down
Loading