mirror of
https://github.com/minetest/minetest.git
synced 2024-11-30 03:23:45 +01:00
minecraft-like crafting
This commit is contained in:
parent
63e27380dc
commit
699d0e9a5e
4
Makefile
4
Makefile
@ -1,7 +1,7 @@
|
|||||||
# Makefile for Irrlicht Examples
|
# Makefile for Irrlicht Examples
|
||||||
# It's usually sufficient to change just the target name and source file list
|
# It's usually sufficient to change just the target name and source file list
|
||||||
# and be sure that CXX is set to a valid compiler
|
# and be sure that CXX is set to a valid compiler
|
||||||
SOURCE_FILES = guiTextInputMenu.cpp guiInventoryMenu.cpp irrlichtwrapper.cpp guiPauseMenu.cpp defaultsettings.cpp mapnode.cpp tile.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp client.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp main.cpp test.cpp
|
SOURCE_FILES = materials.cpp guiTextInputMenu.cpp guiInventoryMenu.cpp irrlichtwrapper.cpp guiPauseMenu.cpp defaultsettings.cpp mapnode.cpp tile.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp client.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp main.cpp test.cpp
|
||||||
|
|
||||||
DEBUG_TARGET = debugtest
|
DEBUG_TARGET = debugtest
|
||||||
DEBUG_SOURCES = $(addprefix src/, $(SOURCE_FILES))
|
DEBUG_SOURCES = $(addprefix src/, $(SOURCE_FILES))
|
||||||
@ -14,7 +14,7 @@ FAST_BUILD_DIR = fastbuild
|
|||||||
FAST_OBJECTS = $(addprefix $(FAST_BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o))
|
FAST_OBJECTS = $(addprefix $(FAST_BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o))
|
||||||
|
|
||||||
SERVER_TARGET = server
|
SERVER_TARGET = server
|
||||||
SERVER_SOURCE_FILES = defaultsettings.cpp mapnode.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp servermain.cpp test.cpp
|
SERVER_SOURCE_FILES = materials.cpp defaultsettings.cpp mapnode.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp servermain.cpp test.cpp
|
||||||
SERVER_SOURCES = $(addprefix src/, $(SERVER_SOURCE_FILES))
|
SERVER_SOURCES = $(addprefix src/, $(SERVER_SOURCE_FILES))
|
||||||
SERVER_BUILD_DIR = serverbuild
|
SERVER_BUILD_DIR = serverbuild
|
||||||
SERVER_OBJECTS = $(addprefix $(SERVER_BUILD_DIR)/, $(SERVER_SOURCE_FILES:.cpp=.o))
|
SERVER_OBJECTS = $(addprefix $(SERVER_BUILD_DIR)/, $(SERVER_SOURCE_FILES:.cpp=.o))
|
||||||
|
BIN
data/stick.png
Normal file
BIN
data/stick.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 947 B |
BIN
data/wood.png
Normal file
BIN
data/wood.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
@ -390,6 +390,20 @@ public:
|
|||||||
{
|
{
|
||||||
return m_wear;
|
return m_wear;
|
||||||
}
|
}
|
||||||
|
// Returns true if weared out
|
||||||
|
bool addWear(u16 add)
|
||||||
|
{
|
||||||
|
if(m_wear >= 65535 - add)
|
||||||
|
{
|
||||||
|
m_wear = 65535;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_wear += add;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
std::string m_toolname;
|
std::string m_toolname;
|
||||||
u16 m_wear;
|
u16 m_wear;
|
||||||
|
102
src/main.cpp
102
src/main.cpp
@ -167,6 +167,8 @@ TODO: Better handling of objects and mobs
|
|||||||
- Make separate classes for client and server
|
- Make separate classes for client and server
|
||||||
- Client should not discriminate between blocks, server should
|
- Client should not discriminate between blocks, server should
|
||||||
- Make other players utilize the same framework
|
- Make other players utilize the same framework
|
||||||
|
- This is also needed for objects that don't get sent to client
|
||||||
|
but are used for triggers etc
|
||||||
|
|
||||||
TODO: Draw big amounts of torches better (that is, throw them in the
|
TODO: Draw big amounts of torches better (that is, throw them in the
|
||||||
same meshbuffer (can the meshcollector class be used?))
|
same meshbuffer (can the meshcollector class be used?))
|
||||||
@ -174,6 +176,9 @@ TODO: Draw big amounts of torches better (that is, throw them in the
|
|||||||
TODO: Check if the usage of Client::isFetchingBlocks() in
|
TODO: Check if the usage of Client::isFetchingBlocks() in
|
||||||
updateViewingRange() actually does something
|
updateViewingRange() actually does something
|
||||||
|
|
||||||
|
TODO: Make an option to the server to disable building and digging near
|
||||||
|
the starting position
|
||||||
|
|
||||||
Doing now:
|
Doing now:
|
||||||
======================================================================
|
======================================================================
|
||||||
|
|
||||||
@ -239,6 +244,7 @@ TODO: Transferring of the table from server to client
|
|||||||
#include "guiPauseMenu.h"
|
#include "guiPauseMenu.h"
|
||||||
#include "guiInventoryMenu.h"
|
#include "guiInventoryMenu.h"
|
||||||
#include "guiTextInputMenu.h"
|
#include "guiTextInputMenu.h"
|
||||||
|
#include "materials.h"
|
||||||
|
|
||||||
IrrlichtWrapper *g_irrlicht;
|
IrrlichtWrapper *g_irrlicht;
|
||||||
|
|
||||||
@ -1022,6 +1028,22 @@ private:
|
|||||||
s32 m_selection;
|
s32 m_selection;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Chat data
|
||||||
|
struct ChatLine
|
||||||
|
{
|
||||||
|
ChatLine():
|
||||||
|
age(0.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
ChatLine(const std::wstring &a_text):
|
||||||
|
age(0.0),
|
||||||
|
text(a_text)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
float age;
|
||||||
|
std::wstring text;
|
||||||
|
};
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -1039,6 +1061,8 @@ int main(int argc, char *argv[])
|
|||||||
debug_stacks_init();
|
debug_stacks_init();
|
||||||
|
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
|
initializeMaterialProperties();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -1541,8 +1565,7 @@ int main(int argc, char *argv[])
|
|||||||
L"Chat here\nOther line\nOther line\nOther line\nOther line",
|
L"Chat here\nOther line\nOther line\nOther line\nOther line",
|
||||||
core::rect<s32>(70, 60, 795, 150),
|
core::rect<s32>(70, 60, 795, 150),
|
||||||
false, true);
|
false, true);
|
||||||
core::list<std::wstring> chat_lines;
|
core::list<ChatLine> chat_lines;
|
||||||
//chat_lines.push_back(L"Minetest-c55 up and running!");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Some statistics are collected in these
|
Some statistics are collected in these
|
||||||
@ -2102,34 +2125,38 @@ int main(int argc, char *argv[])
|
|||||||
if(g_input->getLeftState())
|
if(g_input->getLeftState())
|
||||||
{
|
{
|
||||||
MapNode n = client.getNode(nodepos);
|
MapNode n = client.getNode(nodepos);
|
||||||
|
|
||||||
// TODO: Get this from some table that is sent by server
|
// Get tool name. Default is "" = bare hands
|
||||||
float dig_time_complete = 0.5;
|
std::string toolname = "";
|
||||||
if(n.d == CONTENT_STONE || n.d == CONTENT_COALSTONE)
|
InventoryList *mlist = local_inventory.getList("main");
|
||||||
|
if(mlist != NULL)
|
||||||
{
|
{
|
||||||
dig_time_complete = 10.0;
|
InventoryItem *item = mlist->getItem(g_selected_item);
|
||||||
|
if(item && (std::string)item->getName() == "ToolItem")
|
||||||
InventoryList *mlist = local_inventory.getList("main");
|
|
||||||
if(mlist != NULL)
|
|
||||||
{
|
{
|
||||||
InventoryItem *item = mlist->getItem(g_selected_item);
|
ToolItem *titem = (ToolItem*)item;
|
||||||
if(item && (std::string)item->getName() == "ToolItem")
|
toolname = titem->getToolName();
|
||||||
{
|
|
||||||
ToolItem *titem = (ToolItem*)item;
|
|
||||||
if(titem->getToolName() == "WPick")
|
|
||||||
{
|
|
||||||
dig_time_complete = 1.2;
|
|
||||||
}
|
|
||||||
else if(titem->getToolName() == "STPick")
|
|
||||||
{
|
|
||||||
dig_time_complete = 0.6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(n.d == CONTENT_TORCH)
|
|
||||||
|
// Get digging properties for material and tool
|
||||||
|
u8 material = n.d;
|
||||||
|
DiggingProperties prop =
|
||||||
|
getDiggingProperties(material, toolname);
|
||||||
|
|
||||||
|
float dig_time_complete = 0.0;
|
||||||
|
|
||||||
|
if(prop.diggable == false)
|
||||||
{
|
{
|
||||||
dig_time_complete = 0.0;
|
/*dstream<<"Material "<<(int)material
|
||||||
|
<<" not diggable with \""
|
||||||
|
<<toolname<<"\""<<std::endl;*/
|
||||||
|
// I guess nobody will wait for this long
|
||||||
|
dig_time_complete = 10000000.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dig_time_complete = prop.time;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dig_time_complete >= 0.001)
|
if(dig_time_complete >= 0.001)
|
||||||
@ -2305,14 +2332,14 @@ int main(int argc, char *argv[])
|
|||||||
Get chat messages from client
|
Get chat messages from client
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
// Get messages
|
// Get new messages
|
||||||
std::wstring message;
|
std::wstring message;
|
||||||
while(client.getChatMessage(message))
|
while(client.getChatMessage(message))
|
||||||
{
|
{
|
||||||
chat_lines.push_back(message);
|
chat_lines.push_back(ChatLine(message));
|
||||||
if(chat_lines.size() > 5)
|
if(chat_lines.size() > 7)
|
||||||
{
|
{
|
||||||
core::list<std::wstring>::Iterator
|
core::list<ChatLine>::Iterator
|
||||||
i = chat_lines.begin();
|
i = chat_lines.begin();
|
||||||
chat_lines.erase(i);
|
chat_lines.erase(i);
|
||||||
}
|
}
|
||||||
@ -2320,11 +2347,24 @@ int main(int argc, char *argv[])
|
|||||||
// Append them to form the whole static text and throw
|
// Append them to form the whole static text and throw
|
||||||
// it to the gui element
|
// it to the gui element
|
||||||
std::wstring whole;
|
std::wstring whole;
|
||||||
for(core::list<std::wstring>::Iterator
|
u16 to_be_removed_count = 0;
|
||||||
|
for(core::list<ChatLine>::Iterator
|
||||||
i = chat_lines.begin();
|
i = chat_lines.begin();
|
||||||
i != chat_lines.end(); i++)
|
i != chat_lines.end(); i++)
|
||||||
{
|
{
|
||||||
whole += (*i) + L'\n';
|
(*i).age += dtime;
|
||||||
|
if((*i).age > 30.0)
|
||||||
|
{
|
||||||
|
to_be_removed_count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
whole += (*i).text + L'\n';
|
||||||
|
}
|
||||||
|
for(u16 i=0; i<to_be_removed_count; i++)
|
||||||
|
{
|
||||||
|
core::list<ChatLine>::Iterator
|
||||||
|
i = chat_lines.begin();
|
||||||
|
chat_lines.erase(i);
|
||||||
}
|
}
|
||||||
chat_guitext->setText(whole.c_str());
|
chat_guitext->setText(whole.c_str());
|
||||||
// Update gui element size and position
|
// Update gui element size and position
|
||||||
|
@ -43,6 +43,7 @@ u16 g_content_tiles[USEFUL_CONTENT_COUNT][6] =
|
|||||||
{TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER},
|
{TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER},
|
||||||
{TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD},
|
{TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD},
|
||||||
{TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE},
|
{TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE},
|
||||||
|
{TILE_WOOD,TILE_WOOD,TILE_WOOD,TILE_WOOD,TILE_WOOD,TILE_WOOD},
|
||||||
};
|
};
|
||||||
|
|
||||||
const char * g_content_inventory_textures[USEFUL_CONTENT_COUNT] =
|
const char * g_content_inventory_textures[USEFUL_CONTENT_COUNT] =
|
||||||
@ -59,5 +60,6 @@ const char * g_content_inventory_textures[USEFUL_CONTENT_COUNT] =
|
|||||||
"../data/water.png",
|
"../data/water.png",
|
||||||
"../data/cloud.png",
|
"../data/cloud.png",
|
||||||
"../data/coalstone.png",
|
"../data/coalstone.png",
|
||||||
|
"../data/wood.png",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,6 +77,7 @@ enum Content
|
|||||||
CONTENT_OCEAN,
|
CONTENT_OCEAN,
|
||||||
CONTENT_CLOUD,
|
CONTENT_CLOUD,
|
||||||
CONTENT_COALSTONE,
|
CONTENT_COALSTONE,
|
||||||
|
CONTENT_WOOD,
|
||||||
|
|
||||||
// This is set to the number of the actual values in this enum
|
// This is set to the number of the actual values in this enum
|
||||||
USEFUL_CONTENT_COUNT
|
USEFUL_CONTENT_COUNT
|
||||||
@ -96,6 +97,7 @@ inline bool light_propagates_content(u8 m)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
If true, the material allows lossless sunlight propagation.
|
If true, the material allows lossless sunlight propagation.
|
||||||
|
NOTE: It doesn't seem to go through torches regardlessly of this
|
||||||
*/
|
*/
|
||||||
inline bool sunlight_propagates_content(u8 m)
|
inline bool sunlight_propagates_content(u8 m)
|
||||||
{
|
{
|
||||||
@ -153,14 +155,12 @@ inline bool content_buildable_to(u8 m)
|
|||||||
*/
|
*/
|
||||||
inline bool is_ground_content(u8 m)
|
inline bool is_ground_content(u8 m)
|
||||||
{
|
{
|
||||||
return(
|
return (m != CONTENT_WATER
|
||||||
m == CONTENT_STONE ||
|
&& m != CONTENT_TORCH
|
||||||
m == CONTENT_GRASS ||
|
&& m != CONTENT_TREE
|
||||||
m == CONTENT_GRASS_FOOTSTEPS ||
|
&& m != CONTENT_LEAVES
|
||||||
m == CONTENT_MESE ||
|
&& m != CONTENT_OCEAN
|
||||||
m == CONTENT_MUD ||
|
&& m != CONTENT_CLOUD);
|
||||||
m == CONTENT_COALSTONE
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_mineral(u8 c)
|
inline bool is_mineral(u8 c)
|
||||||
@ -169,12 +169,18 @@ inline bool is_mineral(u8 c)
|
|||||||
|| c == CONTENT_COALSTONE);
|
|| c == CONTENT_COALSTONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*inline bool content_has_faces(u8 c)
|
inline bool liquid_replaces_content(u8 c)
|
||||||
{
|
{
|
||||||
return (m != CONTENT_IGNORE
|
return (c == CONTENT_AIR || c == CONTENT_TORCH);
|
||||||
&& m != CONTENT_AIR
|
}
|
||||||
&& m != CONTENT_TORCH);
|
|
||||||
}*/
|
/*
|
||||||
|
When placing a node, drection info is added to it if this is true
|
||||||
|
*/
|
||||||
|
inline bool content_directional(u8 c)
|
||||||
|
{
|
||||||
|
return (c == CONTENT_TORCH);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Nodes make a face if contents differ and solidness differs.
|
Nodes make a face if contents differ and solidness differs.
|
||||||
@ -201,19 +207,6 @@ inline u8 face_contents(u8 m1, u8 m2)
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool liquid_replaces_content(u8 c)
|
|
||||||
{
|
|
||||||
return (c == CONTENT_AIR || c == CONTENT_TORCH);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
When placing a node, drection info is added to it if this is true
|
|
||||||
*/
|
|
||||||
inline bool content_directional(u8 c)
|
|
||||||
{
|
|
||||||
return (c == CONTENT_TORCH);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Packs directions like (1,0,0), (1,-1,0)
|
Packs directions like (1,0,0), (1,-1,0)
|
||||||
*/
|
*/
|
||||||
|
75
src/materials.cpp
Normal file
75
src/materials.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#include "materials.h"
|
||||||
|
|
||||||
|
#define MATERIAL_PROPERTIES_COUNT 256
|
||||||
|
|
||||||
|
// These correspond to the CONTENT_* constants
|
||||||
|
MaterialProperties g_material_properties[MATERIAL_PROPERTIES_COUNT];
|
||||||
|
|
||||||
|
bool g_material_properties_initialized = false;
|
||||||
|
|
||||||
|
void setStoneLikeDiggingProperties(u8 material, float toughness)
|
||||||
|
{
|
||||||
|
g_material_properties[material].setDiggingProperties("",
|
||||||
|
DiggingProperties(true, 15.0*toughness, 0));
|
||||||
|
g_material_properties[material].setDiggingProperties("WPick",
|
||||||
|
DiggingProperties(true, 2.0*toughness, 65535./20.*toughness));
|
||||||
|
g_material_properties[material].setDiggingProperties("STPick",
|
||||||
|
DiggingProperties(true, 1.0*toughness, 65535./50.*toughness));
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeMaterialProperties()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Now, the g_material_properties array is already initialized
|
||||||
|
by the constructors to such that no digging is possible.
|
||||||
|
|
||||||
|
Add some digging properties to them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
setStoneLikeDiggingProperties(CONTENT_STONE, 1.0);
|
||||||
|
|
||||||
|
g_material_properties[CONTENT_GRASS].setDiggingProperties("",
|
||||||
|
DiggingProperties(true, 0.5, 0));
|
||||||
|
|
||||||
|
g_material_properties[CONTENT_TORCH].setDiggingProperties("",
|
||||||
|
DiggingProperties(true, 0.0, 0));
|
||||||
|
|
||||||
|
g_material_properties[CONTENT_TREE].setDiggingProperties("",
|
||||||
|
DiggingProperties(true, 1.5, 0));
|
||||||
|
|
||||||
|
g_material_properties[CONTENT_LEAVES].setDiggingProperties("",
|
||||||
|
DiggingProperties(true, 0.5, 0));
|
||||||
|
|
||||||
|
g_material_properties[CONTENT_GRASS_FOOTSTEPS].setDiggingProperties("",
|
||||||
|
DiggingProperties(true, 0.5, 0));
|
||||||
|
|
||||||
|
setStoneLikeDiggingProperties(CONTENT_MESE, 0.5);
|
||||||
|
|
||||||
|
g_material_properties[CONTENT_MUD].setDiggingProperties("",
|
||||||
|
DiggingProperties(true, 0.5, 0));
|
||||||
|
|
||||||
|
setStoneLikeDiggingProperties(CONTENT_COALSTONE, 1.5);
|
||||||
|
|
||||||
|
g_material_properties[CONTENT_WOOD].setDiggingProperties("",
|
||||||
|
DiggingProperties(true, 1.0, 0));
|
||||||
|
|
||||||
|
|
||||||
|
g_material_properties_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialProperties * getMaterialProperties(u8 material)
|
||||||
|
{
|
||||||
|
assert(g_material_properties_initialized);
|
||||||
|
return &g_material_properties[material];
|
||||||
|
}
|
||||||
|
|
||||||
|
DiggingProperties getDiggingProperties(u8 material, const std::string &tool)
|
||||||
|
{
|
||||||
|
MaterialProperties *mprop = getMaterialProperties(material);
|
||||||
|
if(mprop == NULL)
|
||||||
|
// Not diggable
|
||||||
|
return DiggingProperties();
|
||||||
|
|
||||||
|
return mprop->getDiggingProperties(tool);
|
||||||
|
}
|
||||||
|
|
98
src/materials.h
Normal file
98
src/materials.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MATERIALS_HEADER
|
||||||
|
#define MATERIALS_HEADER
|
||||||
|
|
||||||
|
/*
|
||||||
|
Material properties
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common_irrlicht.h"
|
||||||
|
#include "inventory.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
struct DiggingProperties
|
||||||
|
{
|
||||||
|
DiggingProperties():
|
||||||
|
diggable(false),
|
||||||
|
time(0.0),
|
||||||
|
wear(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
DiggingProperties(bool a_diggable, float a_time, u16 a_wear):
|
||||||
|
diggable(a_diggable),
|
||||||
|
time(a_time),
|
||||||
|
wear(a_wear)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
bool diggable;
|
||||||
|
// Digging time in seconds
|
||||||
|
float time;
|
||||||
|
// Caused wear
|
||||||
|
u16 wear;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MaterialProperties
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MaterialProperties()
|
||||||
|
{
|
||||||
|
dstream<<__FUNCTION_NAME<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDiggingProperties(const std::string toolname,
|
||||||
|
const DiggingProperties &prop)
|
||||||
|
{
|
||||||
|
m_digging_properties[toolname] = prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiggingProperties getDiggingProperties(const std::string toolname)
|
||||||
|
{
|
||||||
|
core::map<std::string, DiggingProperties>::Node *n;
|
||||||
|
n = m_digging_properties.find(toolname);
|
||||||
|
if(n == NULL)
|
||||||
|
{
|
||||||
|
// Not diggable by this tool, try to get defaults
|
||||||
|
n = m_digging_properties.find("");
|
||||||
|
if(n == NULL)
|
||||||
|
{
|
||||||
|
// Not diggable at all
|
||||||
|
return DiggingProperties();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Return found properties
|
||||||
|
return n->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// toolname="": default properties (digging by hand)
|
||||||
|
// Key is toolname
|
||||||
|
core::map<std::string, DiggingProperties> m_digging_properties;
|
||||||
|
};
|
||||||
|
|
||||||
|
void initializeMaterialProperties();
|
||||||
|
|
||||||
|
// Material correspond to the CONTENT_* constants
|
||||||
|
MaterialProperties * getMaterialProperties(u8 material);
|
||||||
|
// For getting the default properties, set tool=""
|
||||||
|
DiggingProperties getDiggingProperties(u8 material, const std::string &tool);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
473
src/server.cpp
473
src/server.cpp
@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "voxel.h"
|
#include "voxel.h"
|
||||||
|
#include "materials.h"
|
||||||
|
|
||||||
#define BLOCK_EMERGE_FLAG_FROMDISK (1<<0)
|
#define BLOCK_EMERGE_FLAG_FROMDISK (1<<0)
|
||||||
|
|
||||||
@ -1821,9 +1822,47 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||||||
|
|
||||||
if(g_settings.getBool("creative_mode") == false)
|
if(g_settings.getBool("creative_mode") == false)
|
||||||
{
|
{
|
||||||
// Add to inventory and send inventory
|
/*
|
||||||
|
Wear out tool
|
||||||
|
*/
|
||||||
|
InventoryList *mlist = player->inventory.getList("main");
|
||||||
|
if(mlist != NULL)
|
||||||
|
{
|
||||||
|
InventoryItem *item = mlist->getItem(item_i);
|
||||||
|
if(item && (std::string)item->getName() == "ToolItem")
|
||||||
|
{
|
||||||
|
ToolItem *titem = (ToolItem*)item;
|
||||||
|
std::string toolname = titem->getToolName();
|
||||||
|
|
||||||
|
// Get digging properties for material and tool
|
||||||
|
DiggingProperties prop =
|
||||||
|
getDiggingProperties(material, toolname);
|
||||||
|
|
||||||
|
if(prop.diggable == false)
|
||||||
|
{
|
||||||
|
derr_server<<"Server: WARNING: Player digged"
|
||||||
|
<<" with impossible material + tool"
|
||||||
|
<<" combination"<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool weared_out = titem->addWear(prop.wear);
|
||||||
|
|
||||||
|
if(weared_out)
|
||||||
|
{
|
||||||
|
mlist->deleteItem(item_i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add digged item to inventory
|
||||||
|
*/
|
||||||
InventoryItem *item = new MaterialItem(material, 1);
|
InventoryItem *item = new MaterialItem(material, 1);
|
||||||
player->inventory.addItem("main", item);
|
player->inventory.addItem("main", item);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Send inventory
|
||||||
|
*/
|
||||||
SendInventory(player->peer_id);
|
SendInventory(player->peer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2404,138 +2443,6 @@ void Server::peerAdded(con::Peer *peer)
|
|||||||
c.peer_id = peer->id;
|
c.peer_id = peer->id;
|
||||||
c.timeout = false;
|
c.timeout = false;
|
||||||
m_peer_change_queue.push_back(c);
|
m_peer_change_queue.push_back(c);
|
||||||
|
|
||||||
#if 0
|
|
||||||
// NOTE: Connection is already locked when this is called.
|
|
||||||
// NOTE: Environment is already locked when this is called.
|
|
||||||
|
|
||||||
// Error check
|
|
||||||
core::map<u16, RemoteClient*>::Node *n;
|
|
||||||
n = m_clients.find(peer->id);
|
|
||||||
// The client shouldn't already exist
|
|
||||||
assert(n == NULL);
|
|
||||||
|
|
||||||
// Create client
|
|
||||||
RemoteClient *client = new RemoteClient();
|
|
||||||
client->peer_id = peer->id;
|
|
||||||
m_clients.insert(client->peer_id, client);
|
|
||||||
|
|
||||||
// Create player
|
|
||||||
{
|
|
||||||
Player *player = m_env.getPlayer(peer->id);
|
|
||||||
|
|
||||||
// The player shouldn't already exist
|
|
||||||
assert(player == NULL);
|
|
||||||
|
|
||||||
player = new ServerRemotePlayer();
|
|
||||||
player->peer_id = peer->id;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Set player position
|
|
||||||
*/
|
|
||||||
|
|
||||||
// We're going to throw the player to this position
|
|
||||||
//v2s16 nodepos(29990,29990);
|
|
||||||
//v2s16 nodepos(9990,9990);
|
|
||||||
v2s16 nodepos(0,0);
|
|
||||||
v2s16 sectorpos = getNodeSectorPos(nodepos);
|
|
||||||
// Get zero sector (it could have been unloaded to disk)
|
|
||||||
m_env.getMap().emergeSector(sectorpos);
|
|
||||||
// Get ground height at origin
|
|
||||||
f32 groundheight = m_env.getMap().getGroundHeight(nodepos, true);
|
|
||||||
// The sector should have been generated -> groundheight exists
|
|
||||||
assert(groundheight > GROUNDHEIGHT_VALID_MINVALUE);
|
|
||||||
// Don't go underwater
|
|
||||||
if(groundheight < WATER_LEVEL)
|
|
||||||
groundheight = WATER_LEVEL;
|
|
||||||
|
|
||||||
player->setPosition(intToFloat(v3s16(
|
|
||||||
nodepos.X,
|
|
||||||
groundheight + 1,
|
|
||||||
nodepos.Y
|
|
||||||
)));
|
|
||||||
|
|
||||||
/*
|
|
||||||
Add player to environment
|
|
||||||
*/
|
|
||||||
|
|
||||||
m_env.addPlayer(player);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Add stuff to inventory
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(g_settings.getBool("creative_mode"))
|
|
||||||
{
|
|
||||||
// Give a good pick
|
|
||||||
{
|
|
||||||
InventoryItem *item = new ToolItem("STPick", 32000);
|
|
||||||
void* r = player->inventory.addItem("main", item);
|
|
||||||
assert(r == NULL);
|
|
||||||
}
|
|
||||||
// Give all materials
|
|
||||||
assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE);
|
|
||||||
for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
|
|
||||||
{
|
|
||||||
// Skip some materials
|
|
||||||
if(i == CONTENT_OCEAN)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
InventoryItem *item = new MaterialItem(i, 1);
|
|
||||||
player->inventory.addItem("main", item);
|
|
||||||
}
|
|
||||||
// Sign
|
|
||||||
{
|
|
||||||
InventoryItem *item = new MapBlockObjectItem("Sign Example text");
|
|
||||||
void* r = player->inventory.addItem("main", item);
|
|
||||||
assert(r == NULL);
|
|
||||||
}
|
|
||||||
/*// Rat
|
|
||||||
{
|
|
||||||
InventoryItem *item = new MapBlockObjectItem("Rat");
|
|
||||||
bool r = player->inventory.addItem("main", item);
|
|
||||||
assert(r == true);
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
{
|
|
||||||
InventoryItem *item = new CraftItem("Stick", 4);
|
|
||||||
void* r = player->inventory.addItem("main", item);
|
|
||||||
assert(r == NULL);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
InventoryItem *item = new ToolItem("WPick", 32000);
|
|
||||||
void* r = player->inventory.addItem("main", item);
|
|
||||||
assert(r == NULL);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
InventoryItem *item = new ToolItem("STPick", 32000);
|
|
||||||
void* r = player->inventory.addItem("main", item);
|
|
||||||
assert(r == NULL);
|
|
||||||
}
|
|
||||||
/*// Give some lights
|
|
||||||
{
|
|
||||||
InventoryItem *item = new MaterialItem(CONTENT_TORCH, 999);
|
|
||||||
bool r = player->inventory.addItem("main", item);
|
|
||||||
assert(r == true);
|
|
||||||
}
|
|
||||||
// and some signs
|
|
||||||
for(u16 i=0; i<4; i++)
|
|
||||||
{
|
|
||||||
InventoryItem *item = new MapBlockObjectItem("Sign Example text");
|
|
||||||
bool r = player->inventory.addItem("main", item);
|
|
||||||
assert(r == true);
|
|
||||||
}*/
|
|
||||||
/*// Give some other stuff
|
|
||||||
{
|
|
||||||
InventoryItem *item = new MaterialItem(CONTENT_TREE, 999);
|
|
||||||
bool r = player->inventory.addItem("main", item);
|
|
||||||
assert(r == true);
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::deletingPeer(con::Peer *peer, bool timeout)
|
void Server::deletingPeer(con::Peer *peer, bool timeout)
|
||||||
@ -2549,46 +2456,6 @@ void Server::deletingPeer(con::Peer *peer, bool timeout)
|
|||||||
c.peer_id = peer->id;
|
c.peer_id = peer->id;
|
||||||
c.timeout = timeout;
|
c.timeout = timeout;
|
||||||
m_peer_change_queue.push_back(c);
|
m_peer_change_queue.push_back(c);
|
||||||
|
|
||||||
#if 0
|
|
||||||
// NOTE: Connection is already locked when this is called.
|
|
||||||
|
|
||||||
// NOTE: Environment is already locked when this is called.
|
|
||||||
// NOTE: Locking environment cannot be moved here because connection
|
|
||||||
// is already locked and env has to be locked before
|
|
||||||
|
|
||||||
// Error check
|
|
||||||
core::map<u16, RemoteClient*>::Node *n;
|
|
||||||
n = m_clients.find(peer->id);
|
|
||||||
// The client should exist
|
|
||||||
assert(n != NULL);
|
|
||||||
|
|
||||||
// Send information about leaving in chat
|
|
||||||
{
|
|
||||||
std::wstring name = L"unknown";
|
|
||||||
Player *player = m_env.getPlayer(peer->id);
|
|
||||||
if(player != NULL)
|
|
||||||
name = narrow_to_wide(player->getName());
|
|
||||||
|
|
||||||
std::wstring message;
|
|
||||||
message += L"*** ";
|
|
||||||
message += name;
|
|
||||||
message += L" left game";
|
|
||||||
BroadcastChatMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete player
|
|
||||||
{
|
|
||||||
m_env.removePlayer(peer->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete client
|
|
||||||
delete m_clients[peer->id];
|
|
||||||
m_clients.remove(peer->id);
|
|
||||||
|
|
||||||
// Send player info to all clients
|
|
||||||
SendPlayerInfos();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::SendObjectData(float dtime)
|
void Server::SendObjectData(float dtime)
|
||||||
@ -2647,6 +2514,159 @@ void Server::SendPlayerInfos()
|
|||||||
m_con.SendToAll(0, data, true);
|
m_con.SendToAll(0, data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ItemSpecType
|
||||||
|
{
|
||||||
|
ITEM_NONE,
|
||||||
|
ITEM_MATERIAL,
|
||||||
|
ITEM_CRAFT,
|
||||||
|
ITEM_TOOL,
|
||||||
|
ITEM_MBO
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ItemSpec
|
||||||
|
{
|
||||||
|
ItemSpec():
|
||||||
|
type(ITEM_NONE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
ItemSpec(enum ItemSpecType a_type, std::string a_name):
|
||||||
|
type(a_type),
|
||||||
|
name(a_name),
|
||||||
|
num(65535)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
ItemSpec(enum ItemSpecType a_type, u16 a_num):
|
||||||
|
type(a_type),
|
||||||
|
name(""),
|
||||||
|
num(a_num)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
enum ItemSpecType type;
|
||||||
|
// Only other one of these is used
|
||||||
|
std::string name;
|
||||||
|
u16 num;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
items: a pointer to an array of 9 pointers to items
|
||||||
|
specs: a pointer to an array of 9 ItemSpecs
|
||||||
|
*/
|
||||||
|
bool checkItemCombination(InventoryItem **items, ItemSpec *specs)
|
||||||
|
{
|
||||||
|
u16 items_min_x = 100;
|
||||||
|
u16 items_max_x = 100;
|
||||||
|
u16 items_min_y = 100;
|
||||||
|
u16 items_max_y = 100;
|
||||||
|
for(u16 y=0; y<3; y++)
|
||||||
|
for(u16 x=0; x<3; x++)
|
||||||
|
{
|
||||||
|
if(items[y*3 + x] == NULL)
|
||||||
|
continue;
|
||||||
|
if(items_min_x == 100 || x < items_min_x)
|
||||||
|
items_min_x = x;
|
||||||
|
if(items_min_y == 100 || y < items_min_y)
|
||||||
|
items_min_y = y;
|
||||||
|
if(items_max_x == 100 || x > items_max_x)
|
||||||
|
items_max_x = x;
|
||||||
|
if(items_max_y == 100 || y > items_max_y)
|
||||||
|
items_max_y = y;
|
||||||
|
}
|
||||||
|
// No items at all, just return false
|
||||||
|
if(items_min_x == 100)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
u16 items_w = items_max_x - items_min_x + 1;
|
||||||
|
u16 items_h = items_max_y - items_min_y + 1;
|
||||||
|
|
||||||
|
u16 specs_min_x = 100;
|
||||||
|
u16 specs_max_x = 100;
|
||||||
|
u16 specs_min_y = 100;
|
||||||
|
u16 specs_max_y = 100;
|
||||||
|
for(u16 y=0; y<3; y++)
|
||||||
|
for(u16 x=0; x<3; x++)
|
||||||
|
{
|
||||||
|
if(specs[y*3 + x].type == ITEM_NONE)
|
||||||
|
continue;
|
||||||
|
if(specs_min_x == 100 || x < specs_min_x)
|
||||||
|
specs_min_x = x;
|
||||||
|
if(specs_min_y == 100 || y < specs_min_y)
|
||||||
|
specs_min_y = y;
|
||||||
|
if(specs_max_x == 100 || x > specs_max_x)
|
||||||
|
specs_max_x = x;
|
||||||
|
if(specs_max_y == 100 || y > specs_max_y)
|
||||||
|
specs_max_y = y;
|
||||||
|
}
|
||||||
|
// No specs at all, just return false
|
||||||
|
if(specs_min_x == 100)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
u16 specs_w = specs_max_x - specs_min_x + 1;
|
||||||
|
u16 specs_h = specs_max_y - specs_min_y + 1;
|
||||||
|
|
||||||
|
// Different sizes
|
||||||
|
if(items_w != specs_w || items_h != specs_h)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for(u16 y=0; y<specs_h; y++)
|
||||||
|
for(u16 x=0; x<specs_w; x++)
|
||||||
|
{
|
||||||
|
u16 items_x = items_min_x + x;
|
||||||
|
u16 items_y = items_min_y + y;
|
||||||
|
u16 specs_x = specs_min_x + x;
|
||||||
|
u16 specs_y = specs_min_y + y;
|
||||||
|
InventoryItem *item = items[items_y * 3 + items_x];
|
||||||
|
ItemSpec &spec = specs[specs_y * 3 + specs_x];
|
||||||
|
|
||||||
|
if(spec.type == ITEM_NONE)
|
||||||
|
{
|
||||||
|
// Has to be no item
|
||||||
|
if(item != NULL)
|
||||||
|
return false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There should be an item
|
||||||
|
if(item == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string itemname = item->getName();
|
||||||
|
|
||||||
|
if(spec.type == ITEM_MATERIAL)
|
||||||
|
{
|
||||||
|
if(itemname != "MaterialItem")
|
||||||
|
return false;
|
||||||
|
MaterialItem *mitem = (MaterialItem*)item;
|
||||||
|
if(mitem->getMaterial() != spec.num)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if(spec.type == ITEM_CRAFT)
|
||||||
|
{
|
||||||
|
if(itemname != "CraftItem")
|
||||||
|
return false;
|
||||||
|
CraftItem *mitem = (CraftItem*)item;
|
||||||
|
if(mitem->getSubName() != spec.name)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if(spec.type == ITEM_TOOL)
|
||||||
|
{
|
||||||
|
// Not supported yet
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
else if(spec.type == ITEM_MBO)
|
||||||
|
{
|
||||||
|
// Not supported yet
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Not supported yet
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Server::SendInventory(u16 peer_id)
|
void Server::SendInventory(u16 peer_id)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
@ -2670,31 +2690,96 @@ void Server::SendInventory(u16 peer_id)
|
|||||||
{
|
{
|
||||||
items[i] = clist->getItem(i);
|
items[i] = clist->getItem(i);
|
||||||
}
|
}
|
||||||
// Sign
|
|
||||||
if(clist->getUsedSlots() == 1 && items[0])
|
bool found = false;
|
||||||
|
|
||||||
|
// Wood
|
||||||
|
if(!found)
|
||||||
{
|
{
|
||||||
if((std::string)items[0]->getName() == "MaterialItem")
|
ItemSpec specs[9];
|
||||||
|
specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_TREE);
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
{
|
{
|
||||||
MaterialItem *mitem = (MaterialItem*)items[0];
|
rlist->addItem(new MaterialItem(CONTENT_WOOD, 4));
|
||||||
if(mitem->getMaterial() == CONTENT_TREE)
|
found = true;
|
||||||
{
|
|
||||||
rlist->addItem(new MapBlockObjectItem("Sign"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Torch
|
|
||||||
if(clist->getUsedSlots() == 2 && items[0] && items[3])
|
// Stick
|
||||||
|
if(!found)
|
||||||
{
|
{
|
||||||
if(
|
ItemSpec specs[9];
|
||||||
(std::string)items[0]->getName() == "MaterialItem"
|
specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
&& ((MaterialItem*)items[0])->getMaterial() == CONTENT_COALSTONE
|
if(checkItemCombination(items, specs))
|
||||||
&& (std::string)items[3]->getName() == "MaterialItem"
|
{
|
||||||
&& ((MaterialItem*)items[3])->getMaterial() == CONTENT_TREE
|
rlist->addItem(new CraftItem("Stick", 4));
|
||||||
)
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign
|
||||||
|
if(!found)
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[4] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[5] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
rlist->addItem(new MapBlockObjectItem("Sign"));
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Torch
|
||||||
|
if(!found)
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_COALSTONE);
|
||||||
|
specs[3] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
{
|
{
|
||||||
rlist->addItem(new MaterialItem(CONTENT_TORCH, 4));
|
rlist->addItem(new MaterialItem(CONTENT_TORCH, 4));
|
||||||
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wooden pick
|
||||||
|
if(!found)
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
|
||||||
|
specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
rlist->addItem(new ToolItem("WPick", 0));
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stone pick
|
||||||
|
if(!found)
|
||||||
|
{
|
||||||
|
ItemSpec specs[9];
|
||||||
|
specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_STONE);
|
||||||
|
specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_STONE);
|
||||||
|
specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_STONE);
|
||||||
|
specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
|
||||||
|
if(checkItemCombination(items, specs))
|
||||||
|
{
|
||||||
|
rlist->addItem(new ToolItem("STPick", 0));
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2958,6 +3043,16 @@ void Server::handlePeerChange(PeerChange &c)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
InventoryItem *item = new MaterialItem(CONTENT_COALSTONE, 6);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InventoryItem *item = new MaterialItem(CONTENT_WOOD, 6);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
InventoryItem *item = new CraftItem("Stick", 4);
|
InventoryItem *item = new CraftItem("Stick", 4);
|
||||||
void* r = player->inventory.addItem("main", item);
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
@ -123,6 +123,8 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
|
initializeMaterialProperties();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ const char * g_tile_texture_paths[TILES_COUNT] =
|
|||||||
"../data/mud_with_grass.png",
|
"../data/mud_with_grass.png",
|
||||||
"../data/cloud.png",
|
"../data/cloud.png",
|
||||||
"../data/coalstone.png",
|
"../data/coalstone.png",
|
||||||
|
"../data/wood.png",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char * tile_texture_path_get(u32 i)
|
const char * tile_texture_path_get(u32 i)
|
||||||
|
@ -40,6 +40,7 @@ enum TileID
|
|||||||
TILE_MUD_WITH_GRASS,
|
TILE_MUD_WITH_GRASS,
|
||||||
TILE_CLOUD,
|
TILE_CLOUD,
|
||||||
TILE_COALSTONE,
|
TILE_COALSTONE,
|
||||||
|
TILE_WOOD,
|
||||||
|
|
||||||
// Count of tile ids
|
// Count of tile ids
|
||||||
TILES_COUNT
|
TILES_COUNT
|
||||||
|
Loading…
Reference in New Issue
Block a user