forked from Mirrorlandia_minetest/minetest
Use place_param2 client-side for item appearance & prediction (#11024)
This commit is contained in:
parent
a21402b38f
commit
bf8fb2672e
@ -3287,7 +3287,8 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
|
|||||||
const ItemStack &selected_item, const v3s16 &nodepos, const v3s16 &neighbourpos,
|
const ItemStack &selected_item, const v3s16 &nodepos, const v3s16 &neighbourpos,
|
||||||
const PointedThing &pointed, const NodeMetadata *meta)
|
const PointedThing &pointed, const NodeMetadata *meta)
|
||||||
{
|
{
|
||||||
std::string prediction = selected_def.node_placement_prediction;
|
const auto &prediction = selected_def.node_placement_prediction;
|
||||||
|
|
||||||
const NodeDefManager *nodedef = client->ndef();
|
const NodeDefManager *nodedef = client->ndef();
|
||||||
ClientMap &map = client->getEnv().getClientMap();
|
ClientMap &map = client->getEnv().getClientMap();
|
||||||
MapNode node;
|
MapNode node;
|
||||||
@ -3357,8 +3358,7 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
|
|||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
errorstream << "Node placement prediction failed for "
|
errorstream << "Node placement prediction failed for "
|
||||||
<< selected_def.name << " (places "
|
<< selected_def.name << " (places " << prediction
|
||||||
<< prediction
|
|
||||||
<< ") - Name not known" << std::endl;
|
<< ") - Name not known" << std::endl;
|
||||||
// Handle this as if prediction was empty
|
// Handle this as if prediction was empty
|
||||||
// Report to server
|
// Report to server
|
||||||
@ -3369,9 +3369,14 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
|
|||||||
const ContentFeatures &predicted_f = nodedef->get(id);
|
const ContentFeatures &predicted_f = nodedef->get(id);
|
||||||
|
|
||||||
// Predict param2 for facedir and wallmounted nodes
|
// Predict param2 for facedir and wallmounted nodes
|
||||||
|
// Compare core.item_place_node() for what the server does
|
||||||
u8 param2 = 0;
|
u8 param2 = 0;
|
||||||
|
|
||||||
if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
|
const u8 place_param2 = selected_def.place_param2;
|
||||||
|
|
||||||
|
if (place_param2) {
|
||||||
|
param2 = place_param2;
|
||||||
|
} else if (predicted_f.param_type_2 == CPT2_WALLMOUNTED ||
|
||||||
predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
|
predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
|
||||||
v3s16 dir = nodepos - neighbourpos;
|
v3s16 dir = nodepos - neighbourpos;
|
||||||
|
|
||||||
@ -3382,9 +3387,7 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
|
|||||||
} else {
|
} else {
|
||||||
param2 = dir.Z < 0 ? 5 : 4;
|
param2 = dir.Z < 0 ? 5 : 4;
|
||||||
}
|
}
|
||||||
}
|
} else if (predicted_f.param_type_2 == CPT2_FACEDIR ||
|
||||||
|
|
||||||
if (predicted_f.param_type_2 == CPT2_FACEDIR ||
|
|
||||||
predicted_f.param_type_2 == CPT2_COLORED_FACEDIR) {
|
predicted_f.param_type_2 == CPT2_COLORED_FACEDIR) {
|
||||||
v3s16 dir = nodepos - floatToInt(client->getEnv().getLocalPlayer()->getPosition(), BS);
|
v3s16 dir = nodepos - floatToInt(client->getEnv().getLocalPlayer()->getPosition(), BS);
|
||||||
|
|
||||||
@ -3395,11 +3398,9 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(param2 <= 5);
|
|
||||||
|
|
||||||
// Check attachment if node is in group attached_node
|
// Check attachment if node is in group attached_node
|
||||||
if (((ItemGroupList) predicted_f.groups)["attached_node"] != 0) {
|
if (itemgroup_get(predicted_f.groups, "attached_node") != 0) {
|
||||||
static v3s16 wallmounted_dirs[8] = {
|
const static v3s16 wallmounted_dirs[8] = {
|
||||||
v3s16(0, 1, 0),
|
v3s16(0, 1, 0),
|
||||||
v3s16(0, -1, 0),
|
v3s16(0, -1, 0),
|
||||||
v3s16(1, 0, 0),
|
v3s16(1, 0, 0),
|
||||||
@ -3424,11 +3425,11 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply color
|
// Apply color
|
||||||
if ((predicted_f.param_type_2 == CPT2_COLOR
|
if (!place_param2 && (predicted_f.param_type_2 == CPT2_COLOR
|
||||||
|| predicted_f.param_type_2 == CPT2_COLORED_FACEDIR
|
|| predicted_f.param_type_2 == CPT2_COLORED_FACEDIR
|
||||||
|| predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED)) {
|
|| predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED)) {
|
||||||
const std::string &indexstr = selected_item.metadata.getString(
|
const auto &indexstr = selected_item.metadata.
|
||||||
"palette_index", 0);
|
getString("palette_index", 0);
|
||||||
if (!indexstr.empty()) {
|
if (!indexstr.empty()) {
|
||||||
s32 index = mystoi(indexstr);
|
s32 index = mystoi(indexstr);
|
||||||
if (predicted_f.param_type_2 == CPT2_COLOR) {
|
if (predicted_f.param_type_2 == CPT2_COLOR) {
|
||||||
@ -3468,11 +3469,10 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
|
|||||||
soundmaker->m_player_rightpunch_sound = selected_def.sound_place_failed;
|
soundmaker->m_player_rightpunch_sound = selected_def.sound_place_failed;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (InvalidPositionException &e) {
|
} catch (const InvalidPositionException &e) {
|
||||||
errorstream << "Node placement prediction failed for "
|
errorstream << "Node placement prediction failed for "
|
||||||
<< selected_def.name << " (places "
|
<< selected_def.name << " (places "
|
||||||
<< prediction
|
<< prediction << ") - Position not loaded" << std::endl;
|
||||||
<< ") - Position not loaded" << std::endl;
|
|
||||||
soundmaker->m_player_rightpunch_sound = selected_def.sound_place_failed;
|
soundmaker->m_player_rightpunch_sound = selected_def.sound_place_failed;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -294,7 +294,7 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename,
|
|||||||
}
|
}
|
||||||
material.setFlag(video::EMF_ANISOTROPIC_FILTER, m_anisotropic_filter);
|
material.setFlag(video::EMF_ANISOTROPIC_FILTER, m_anisotropic_filter);
|
||||||
// mipmaps cause "thin black line" artifacts
|
// mipmaps cause "thin black line" artifacts
|
||||||
#if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2
|
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2
|
||||||
material.setFlag(video::EMF_USE_MIP_MAPS, false);
|
material.setFlag(video::EMF_USE_MIP_MAPS, false);
|
||||||
#endif
|
#endif
|
||||||
if (m_enable_shaders) {
|
if (m_enable_shaders) {
|
||||||
@ -303,23 +303,26 @@ void WieldMeshSceneNode::setExtruded(const std::string &imagename,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scene::SMesh *createSpecialNodeMesh(Client *client, content_t id, std::vector<ItemPartColor> *colors, const ContentFeatures &f)
|
static scene::SMesh *createSpecialNodeMesh(Client *client, MapNode n,
|
||||||
|
std::vector<ItemPartColor> *colors, const ContentFeatures &f)
|
||||||
{
|
{
|
||||||
MeshMakeData mesh_make_data(client, false);
|
MeshMakeData mesh_make_data(client, false);
|
||||||
MeshCollector collector;
|
MeshCollector collector;
|
||||||
mesh_make_data.setSmoothLighting(false);
|
mesh_make_data.setSmoothLighting(false);
|
||||||
MapblockMeshGenerator gen(&mesh_make_data, &collector);
|
MapblockMeshGenerator gen(&mesh_make_data, &collector);
|
||||||
u8 param2 = 0;
|
|
||||||
if (f.param_type_2 == CPT2_WALLMOUNTED ||
|
if (n.getParam2()) {
|
||||||
|
// keep it
|
||||||
|
} else if (f.param_type_2 == CPT2_WALLMOUNTED ||
|
||||||
f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
|
f.param_type_2 == CPT2_COLORED_WALLMOUNTED) {
|
||||||
if (f.drawtype == NDT_TORCHLIKE)
|
if (f.drawtype == NDT_TORCHLIKE)
|
||||||
param2 = 1;
|
n.setParam2(1);
|
||||||
else if (f.drawtype == NDT_SIGNLIKE ||
|
else if (f.drawtype == NDT_SIGNLIKE ||
|
||||||
f.drawtype == NDT_NODEBOX ||
|
f.drawtype == NDT_NODEBOX ||
|
||||||
f.drawtype == NDT_MESH)
|
f.drawtype == NDT_MESH)
|
||||||
param2 = 4;
|
n.setParam2(4);
|
||||||
}
|
}
|
||||||
gen.renderSingle(id, param2);
|
gen.renderSingle(n.getContent(), n.getParam2());
|
||||||
|
|
||||||
colors->clear();
|
colors->clear();
|
||||||
scene::SMesh *mesh = new scene::SMesh();
|
scene::SMesh *mesh = new scene::SMesh();
|
||||||
@ -413,9 +416,12 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
|
|||||||
case NDT_LIQUID:
|
case NDT_LIQUID:
|
||||||
setCube(f, def.wield_scale);
|
setCube(f, def.wield_scale);
|
||||||
break;
|
break;
|
||||||
default:
|
default: {
|
||||||
// Render non-trivial drawtypes like the actual node
|
// Render non-trivial drawtypes like the actual node
|
||||||
mesh = createSpecialNodeMesh(client, id, &m_colors, f);
|
MapNode n(id);
|
||||||
|
n.setParam2(def.place_param2);
|
||||||
|
|
||||||
|
mesh = createSpecialNodeMesh(client, n, &m_colors, f);
|
||||||
changeToMesh(mesh);
|
changeToMesh(mesh);
|
||||||
mesh->drop();
|
mesh->drop();
|
||||||
m_meshnode->setScale(
|
m_meshnode->setScale(
|
||||||
@ -423,6 +429,7 @@ void WieldMeshSceneNode::setItem(const ItemStack &item, Client *client, bool che
|
|||||||
/ (BS * f.visual_scale));
|
/ (BS * f.visual_scale));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u32 material_count = m_meshnode->getMaterialCount();
|
u32 material_count = m_meshnode->getMaterialCount();
|
||||||
for (u32 i = 0; i < material_count; ++i) {
|
for (u32 i = 0; i < material_count; ++i) {
|
||||||
@ -585,12 +592,16 @@ void getItemMesh(Client *client, const ItemStack &item, ItemMesh *result)
|
|||||||
result->buffer_colors.emplace_back(l0.has_color, l0.color);
|
result->buffer_colors.emplace_back(l0.has_color, l0.color);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default: {
|
||||||
// Render non-trivial drawtypes like the actual node
|
// Render non-trivial drawtypes like the actual node
|
||||||
mesh = createSpecialNodeMesh(client, id, &result->buffer_colors, f);
|
MapNode n(id);
|
||||||
|
n.setParam2(def.place_param2);
|
||||||
|
|
||||||
|
mesh = createSpecialNodeMesh(client, n, &result->buffer_colors, f);
|
||||||
scaleMesh(mesh, v3f(0.12, 0.12, 0.12));
|
scaleMesh(mesh, v3f(0.12, 0.12, 0.12));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u32 mc = mesh->getMeshBufferCount();
|
u32 mc = mesh->getMeshBufferCount();
|
||||||
for (u32 i = 0; i < mc; ++i) {
|
for (u32 i = 0; i < mc; ++i) {
|
||||||
|
@ -72,12 +72,10 @@ ItemDefinition& ItemDefinition::operator=(const ItemDefinition &def)
|
|||||||
usable = def.usable;
|
usable = def.usable;
|
||||||
liquids_pointable = def.liquids_pointable;
|
liquids_pointable = def.liquids_pointable;
|
||||||
if (def.tool_capabilities)
|
if (def.tool_capabilities)
|
||||||
{
|
tool_capabilities = new ToolCapabilities(*def.tool_capabilities);
|
||||||
tool_capabilities = new ToolCapabilities(
|
|
||||||
*def.tool_capabilities);
|
|
||||||
}
|
|
||||||
groups = def.groups;
|
groups = def.groups;
|
||||||
node_placement_prediction = def.node_placement_prediction;
|
node_placement_prediction = def.node_placement_prediction;
|
||||||
|
place_param2 = def.place_param2;
|
||||||
sound_place = def.sound_place;
|
sound_place = def.sound_place;
|
||||||
sound_place_failed = def.sound_place_failed;
|
sound_place_failed = def.sound_place_failed;
|
||||||
range = def.range;
|
range = def.range;
|
||||||
@ -120,8 +118,8 @@ void ItemDefinition::reset()
|
|||||||
sound_place = SimpleSoundSpec();
|
sound_place = SimpleSoundSpec();
|
||||||
sound_place_failed = SimpleSoundSpec();
|
sound_place_failed = SimpleSoundSpec();
|
||||||
range = -1;
|
range = -1;
|
||||||
|
|
||||||
node_placement_prediction = "";
|
node_placement_prediction = "";
|
||||||
|
place_param2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
|
void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
|
||||||
@ -166,6 +164,8 @@ void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
|
|||||||
os << serializeString16(wield_overlay);
|
os << serializeString16(wield_overlay);
|
||||||
|
|
||||||
os << serializeString16(short_description);
|
os << serializeString16(short_description);
|
||||||
|
|
||||||
|
os << place_param2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemDefinition::deSerialize(std::istream &is)
|
void ItemDefinition::deSerialize(std::istream &is)
|
||||||
@ -219,6 +219,8 @@ void ItemDefinition::deSerialize(std::istream &is)
|
|||||||
// block to not need to increase the version.
|
// block to not need to increase the version.
|
||||||
try {
|
try {
|
||||||
short_description = deSerializeString16(is);
|
short_description = deSerializeString16(is);
|
||||||
|
|
||||||
|
place_param2 = readU8(is); // 0 if missing
|
||||||
} catch(SerializationError &e) {};
|
} catch(SerializationError &e) {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ struct ItemDefinition
|
|||||||
// Server will update the precise end result a moment later.
|
// Server will update the precise end result a moment later.
|
||||||
// "" = no prediction
|
// "" = no prediction
|
||||||
std::string node_placement_prediction;
|
std::string node_placement_prediction;
|
||||||
|
u8 place_param2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Some helpful methods
|
Some helpful methods
|
||||||
|
@ -119,6 +119,8 @@ void read_item_definition(lua_State* L, int index,
|
|||||||
// "" = no prediction
|
// "" = no prediction
|
||||||
getstringfield(L, index, "node_placement_prediction",
|
getstringfield(L, index, "node_placement_prediction",
|
||||||
def.node_placement_prediction);
|
def.node_placement_prediction);
|
||||||
|
|
||||||
|
getintfield(L, index, "place_param2", def.place_param2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
Loading…
Reference in New Issue
Block a user