Use place_param2 client-side for item appearance & prediction (#11024)

This commit is contained in:
sfan5 2021-03-09 00:56:53 +01:00 committed by GitHub
parent a21402b38f
commit bf8fb2672e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 51 additions and 35 deletions

@ -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);
} }
/******************************************************************************/ /******************************************************************************/