add support for privileged crafting, add mithril key

This commit is contained in:
darkrose 2015-12-08 17:25:46 +10:00
parent 4f00ebe5dc
commit 0373e64007
10 changed files with 91 additions and 33 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 B

BIN
data/textures/tool_key.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 B

View File

@ -31,6 +31,7 @@
#include "content_toolitem.h"
#include "content_list.h"
#include "player.h"
#include "server.h"
#include "mapnode.h" // For content_t
#include "settings.h" // for g_settings
@ -68,7 +69,7 @@ static bool checkShapelessRecipe(content_t recipe[9], content_t result)
return false;
}
void setRecipe(content_t recipe[9], content_t result, u16 count)
void setRecipe(content_t recipe[9], content_t result, u16 count, uint64_t privs)
{
if (checkRecipe(recipe,result))
return;
@ -78,10 +79,11 @@ void setRecipe(content_t recipe[9], content_t result, u16 count)
}
d.result = result;
d.result_count = count;
d.privs = privs;
shaped_recipes.push_back(d);
}
void setShapelessRecipe(content_t recipe[9], content_t result, u16 count)
void setShapelessRecipe(content_t recipe[9], content_t result, u16 count, uint64_t privs)
{
if (checkShapelessRecipe(recipe,result))
return;
@ -91,6 +93,7 @@ void setShapelessRecipe(content_t recipe[9], content_t result, u16 count)
}
d.result = result;
d.result_count = count;
d.privs = privs;
shapeless_recipes.push_back(d);
}
@ -677,15 +680,19 @@ void setShortsRecipe(u16 input, u16 result)
setRecipe(r,result,1);
}
InventoryItem *getResult(InventoryItem **items)
InventoryItem *getResult(InventoryItem **items, Player *player, Server *server)
{
for (std::vector<CraftDef>::iterator i=shaped_recipes.begin(); i!=shaped_recipes.end(); i++) {
CraftDef d = *i;
if (d.privs != 0 && (server->getPlayerPrivs(player)&d.privs) != d.privs)
continue;
if (d == items)
return InventoryItem::create(d.result,d.result_count);
}
for (std::vector<CraftDefShapeless>::iterator i=shapeless_recipes.begin(); i!=shapeless_recipes.end(); i++) {
CraftDefShapeless d = *i;
if (d.privs != 0 && (server->getPlayerPrivs(player)&d.privs) != d.privs)
continue;
if (d == items)
return InventoryItem::create(d.result,d.result_count);
}

View File

@ -29,11 +29,13 @@
#include "inventory.h"
class Player;
class Server;
struct CraftDef {
content_t recipe[9];
content_t result;
u16 result_count;
uint64_t privs;
bool operator==(InventoryItem * const *items)
{
@ -125,6 +127,7 @@ struct CraftDefShapeless {
content_t recipe[9];
content_t result;
u16 result_count;
uint64_t privs;
bool operator==(InventoryItem * const *items)
{
@ -170,8 +173,8 @@ namespace crafting {
void initCrafting();
// add recipes
void setRecipe(u16 recipe[9], u16 result, u16 count);
void setShapelessRecipe(u16 recipe[9], u16 result, u16 count);
void setRecipe(u16 recipe[9], u16 result, u16 count, uint64_t privs = 0);
void setShapelessRecipe(u16 recipe[9], u16 result, u16 count, uint64_t privs = 0);
// shortcuts
// one input yields one result
@ -277,7 +280,7 @@ namespace crafting {
// pants recipe 5 input in an upside-down V yields one result
void setShortsRecipe(u16 input, u16 result);
InventoryItem *getResult(InventoryItem **items);
InventoryItem *getResult(InventoryItem **items, Player *player, Server *server);
content_t *getRecipe(InventoryItem *item);
content_t *getRecipe(InventoryItem *item, int i);
int getResultCount(InventoryItem *item);

View File

@ -3345,7 +3345,8 @@ bool ForgeNodeMetadata::step(float dtime, v3s16 pos, ServerEnvironment *env)
return false;
// Get result of crafting grid
InventoryItem *result = crafting::getResult(items);
/* TODO: player/server args */
InventoryItem *result = crafting::getResult(items,NULL,NULL);
if (!result)
return false;
if (rlist->itemFits(0,result))
@ -3390,7 +3391,8 @@ bool ForgeNodeMetadata::step(float dtime, v3s16 pos, ServerEnvironment *env)
return false;
// Get result of crafting grid
InventoryItem *result = crafting::getResult(items);
/* TODO: player/server args */
InventoryItem *result = crafting::getResult(items,NULL,NULL);
if (!result)
return false;

View File

@ -27,6 +27,7 @@
#include <map>
#include "intl.h"
#include "enchantment.h"
#include "auth.h"
std::map<content_t,struct ToolItemFeatures> g_content_toolitem_features;
@ -599,7 +600,7 @@ void content_toolitem_init()
i = CONTENT_TOOLITEM_KEY;
f = &g_content_toolitem_features[i];
f->content = i;
f->texture = "key.png";
f->texture = "tool_key.png";
f->name = "key";
f->description = wgettext("Key");
f->type = TT_SPECIAL;
@ -899,4 +900,24 @@ void content_toolitem_init()
crafting::setRecipe(r,i,1);
}
lists::add("craftguide",i);
i = CONTENT_TOOLITEM_MITHRIL_KEY;
f = &g_content_toolitem_features[i];
f->content = i;
f->texture = "tool_mithril_key.png";
f->name = "mithrilkey";
f->description = wgettext("Mithril Key");
f->type = TT_SPECIAL;
f->level = 5;
f->has_unlock_effect = true;
f->has_super_unlock_effect = true;
/* this can only be crafted by server admin */
{
content_t r[9] = {
CONTENT_CRAFTITEM_MITHRIL_UNBOUND, CONTENT_IGNORE, CONTENT_IGNORE,
CONTENT_IGNORE, CONTENT_IGNORE, CONTENT_IGNORE,
CONTENT_IGNORE, CONTENT_IGNORE, CONTENT_IGNORE
};
crafting::setRecipe(r,i,1,PRIV_SERVER);
}
}

View File

@ -41,6 +41,7 @@ struct ToolItemFeatures {
bool has_punch_effect;
// whether this tool can lock/unlock nodes
bool has_unlock_effect;
bool has_super_unlock_effect;
// whether this tool can rotate nodes
bool has_rotate_effect;
// whether this tool can start fires
@ -75,6 +76,7 @@ struct ToolItemFeatures {
damaging_nodes_diggable(true),
has_punch_effect(true),
has_unlock_effect(false),
has_super_unlock_effect(false),
has_rotate_effect(false),
has_fire_effect(false),
type(TT_NONE),
@ -163,5 +165,6 @@ ToolItemFeatures & content_toolitem_features(std::string subname);
#define CONTENT_TOOLITEM_MITHRIL_SWORD (CONTENT_TOOLITEM_MASK | 0x2E)
#define CONTENT_TOOLITEM_MITHRIL_SPEAR (CONTENT_TOOLITEM_MASK | 0x2F)
#define CONTENT_TOOLITEM_MOB_SPAWNER (CONTENT_TOOLITEM_MASK | 0x30)
#define CONTENT_TOOLITEM_MITHRIL_KEY (CONTENT_TOOLITEM_MASK | 0x31)
#endif

View File

@ -2497,9 +2497,18 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
if (!wielded_tool_features.has_punch_effect)
return;
// KEY
if (wielded_tool_features.has_unlock_effect && selected_node_features.alternate_lockstate_node != CONTENT_IGNORE) {
if (
wielded_tool_features.has_unlock_effect
&& (
selected_node_features.alternate_lockstate_node != CONTENT_IGNORE
|| (
wielded_tool_features.has_super_unlock_effect
&& selected_content == CONTENT_BORDERSTONE
)
)
) {
NodeMetadata *meta = m_env.getMap().getNodeMetadata(p_under);
if ((getPlayerPrivs(player) & PRIV_SERVER) == 0) {
if ((getPlayerPrivs(player) & PRIV_SERVER) == 0 && !wielded_tool_features.has_super_unlock_effect) {
// non-admins can't unlock other players things
if (meta && meta->getOwner() != player->getName()) {
if (meta->getOwner() != "")
@ -2508,29 +2517,42 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
if (borderstone_locked)
return;
}
content_t c = selected_node_features.alternate_lockstate_node;
NodeMetadata *ometa = NULL;
if (meta) {
if (meta->getEnergy())
return;
ometa = meta->clone();
}
selected_node.setContent(c);
// send the node
core::list<u16> far_players;
core::map<v3s16, MapBlock*> modified_blocks;
sendAddNode(p_under, selected_node, 0, &far_players, 30);
// wear out the key - admin's key doesn't wear
ToolItem *titem = (ToolItem*)wielditem;
if ((getPlayerPrivs(player) & PRIV_SERVER) == 0 && g_settings->getBool("tool_wear")) {
bool weared_out = titem->addWear(10000);
InventoryList *mlist = player->inventory.getList("main");
if (weared_out) {
mlist->deleteItem(item_i);
}else{
mlist->addDiff(item_i,titem);
if (selected_content == CONTENT_BORDERSTONE) {
if (!wielded_tool_features.has_super_unlock_effect)
return;
selected_node.setContent(CONTENT_STONE);
m_env.getMap().removeNodeMetadata(p_under);
// send the node
sendAddNode(p_under, selected_node, 0, &far_players, 30);
}else{
content_t c = selected_node_features.alternate_lockstate_node;
if (meta) {
if (meta->getEnergy())
return;
ometa = meta->clone();
}
selected_node.setContent(c);
// send the node
sendAddNode(p_under, selected_node, 0, &far_players, 30);
// wear out the key - admin's key doesn't wear
ToolItem *titem = (ToolItem*)wielditem;
if (
!wielded_tool_features.has_super_unlock_effect
&& (getPlayerPrivs(player) & PRIV_SERVER) == 0
&& g_settings->getBool("tool_wear")
) {
bool weared_out = titem->addWear(10000);
InventoryList *mlist = player->inventory.getList("main");
if (weared_out) {
mlist->deleteItem(item_i);
}else{
mlist->addDiff(item_i,titem);
}
SendInventory(player->peer_id);
}
SendInventory(player->peer_id);
}
// the slow add to map
{
@ -5643,7 +5665,7 @@ void Server::UpdateCrafting(u16 peer_id)
}
// Get result of crafting grid
InventoryItem *result = crafting::getResult(items);
InventoryItem *result = crafting::getResult(items,player,this);
if (result)
rlist->addItem(result);
}

View File

@ -445,6 +445,8 @@ public:
core::list<Player*> getPlayers() {return m_env.getPlayers();}
core::list<Player*> getPlayers(bool ign_disconnected) {return m_env.getPlayers(ign_disconnected);}
uint64_t getPlayerPrivs(Player *player);
// Saves g_settings to configpath given at initialization
void saveConfig();
@ -570,8 +572,6 @@ private:
void handlePeerChange(PeerChange &c);
void handlePeerChanges();
uint64_t getPlayerPrivs(Player *player);
/*
Variables
*/