Skip to content

Commit 78eb417

Browse files
authored
Merge pull request #82666 from ehughsbaird/veh-optional-2
Use optional/mandatory for more vpart_info fields
2 parents 6bea84f + ea5635a commit 78eb417

File tree

3 files changed

+118
-64
lines changed

3 files changed

+118
-64
lines changed

src/generic_factory.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1389,9 +1389,10 @@ struct T_has_do_delete<T, std::void_t<decltype( &T::do_delete )>> : std::true_ty
13891389
template<typename Derived>
13901390
class generic_typed_reader
13911391
{
1392+
public:
13921393
static constexpr bool read_objects = false;
13931394
static constexpr bool check_extend_delete_copy_from = true;
1394-
public:
1395+
13951396
template<typename C, typename Fn>
13961397
// I tried using a member function pointer and couldn't work it out
13971398
void apply_all_values( JsonValue &jv, C &container, Fn apply ) const {
@@ -1659,6 +1660,8 @@ template<typename T>
16591660
class json_read_reader : public generic_typed_reader<json_read_reader<T>>
16601661
{
16611662
public:
1663+
static constexpr bool read_objects = true;
1664+
16621665
T get_next( const JsonValue &jv ) const {
16631666
T ret;
16641667
if( !jv.read( ret ) ) {

src/veh_type.cpp

Lines changed: 85 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "wcwidth.h"
5151

5252
class emit;
53+
class proficiency;
5354

5455
namespace
5556
{
@@ -204,28 +205,10 @@ static void parse_vp_reqs( const JsonObject &obj, const vpart_id &id, const std:
204205
}
205206
}
206207

207-
static void parse_vp_control_reqs( const JsonObject &obj, const vpart_id &id,
208-
std::string_view key,
209-
vp_control_req &req )
208+
void vp_control_req::deserialize( const JsonObject &jo )
210209
{
211-
if( !obj.has_object( key ) ) {
212-
return;
213-
}
214-
JsonObject src = obj.get_object( key );
215-
216-
JsonArray sk = src.get_array( "skills" );
217-
if( !sk.empty() ) {
218-
req.skills.clear();
219-
for( JsonArray cur : sk ) {
220-
if( cur.size() != 2 ) {
221-
debugmsg( "vpart '%s' has requirement with invalid skill entry", id.str() );
222-
continue;
223-
}
224-
req.skills.emplace( skill_id( cur.get_string( 0 ) ), cur.get_int( 1 ) );
225-
}
226-
}
227-
228-
optional( src, false, "proficiencies", req.proficiencies );
210+
optional( jo, false, "skills", skills, weighted_string_id_reader<skill_id, int> { std::nullopt} );
211+
optional( jo, false, "proficiencies", proficiencies, string_id_reader<proficiency> {} );
229212
}
230213

231214
void vehicles::parts::load( const JsonObject &jo, const std::string &src )
@@ -327,8 +310,8 @@ void vpart_info::load( const JsonObject &jo, const std::string &src )
327310
if( jo.has_member( "control_requirements" ) ) {
328311
JsonObject reqs = jo.get_object( "control_requirements" );
329312

330-
parse_vp_control_reqs( reqs, id, "air", control_air );
331-
parse_vp_control_reqs( reqs, id, "land", control_land );
313+
optional( reqs, false, "air", control_air );
314+
optional( reqs, false, "land", control_land );
332315
}
333316

334317
optional( jo, was_loaded, "looks_like", looks_like, looks_like );
@@ -363,77 +346,116 @@ void vpart_info::load( const JsonObject &jo, const std::string &src )
363346
damage_reduction = load_damage_map( dred );
364347
}
365348

349+
// TODO?: move this into an object?
366350
if( has_flag( "ENGINE" ) ) {
367351
if( !engine_info ) {
368352
engine_info.emplace();
369353
}
370-
assign( jo, "backfire_threshold", engine_info->backfire_threshold, strict );
371-
assign( jo, "backfire_freq", engine_info->backfire_freq, strict );
372-
assign( jo, "noise_factor", engine_info->noise_factor, strict );
373-
assign( jo, "damaged_power_factor", engine_info->damaged_power_factor, strict );
374-
assign( jo, "m2c", engine_info->m2c, strict );
375-
assign( jo, "muscle_power_factor", engine_info->muscle_power_factor, strict );
376-
assign( jo, "exclusions", engine_info->exclusions, strict );
377-
assign( jo, "fuel_options", engine_info->fuel_opts, strict );
354+
engine_info->deserialize( jo );
378355
}
379356

380357
if( has_flag( "WHEEL" ) ) {
381358
if( !wheel_info ) {
382359
wheel_info.emplace();
383360
}
384-
385-
assign( jo, "rolling_resistance", wheel_info->rolling_resistance, strict );
386-
assign( jo, "contact_area", wheel_info->contact_area, strict );
387-
assign( jo, "wheel_offroad_rating", wheel_info->offroad_rating, strict );
388-
if( const std::optional<JsonValue> jo_termod = jo.get_member_opt( "wheel_terrain_modifiers" ) ) {
389-
wheel_info->terrain_modifiers.clear();
390-
for( const JsonMember jo_mod : static_cast<JsonObject>( *jo_termod ) ) {
391-
const JsonArray jo_mod_values = jo_mod.get_array();
392-
veh_ter_mod mod { jo_mod.name(), jo_mod_values.get_int( 0 ), jo_mod_values.get_int( 1 ) };
393-
wheel_info->terrain_modifiers.emplace_back( std::move( mod ) );
394-
}
395-
}
361+
wheel_info->deserialize( jo );
396362
}
397363

398364
if( has_flag( "ROTOR" ) ) {
399365
if( !rotor_info ) {
400366
rotor_info.emplace();
401367
}
402-
assign( jo, "rotor_diameter", rotor_info->rotor_diameter, strict );
368+
rotor_info->deserialize( jo );
403369
}
404370

405371
if( has_flag( "WORKBENCH" ) ) {
406-
if( !workbench_info ) {
407-
workbench_info.emplace();
408-
}
409-
410-
JsonObject wb_jo = jo.get_object( "workbench" );
411-
assign( wb_jo, "multiplier", workbench_info->multiplier, strict );
412-
assign( wb_jo, "mass", workbench_info->allowed_mass, strict );
413-
assign( wb_jo, "volume", workbench_info->allowed_volume, strict );
372+
mandatory( jo, was_loaded, "workbench", workbench_info );
414373
}
415374

416375
if( has_flag( "VEH_TOOLS" ) ) {
417376
if( !toolkit_info ) {
418377
toolkit_info.emplace();
419378
}
420-
assign( jo, "allowed_tools", toolkit_info->allowed_types, strict );
379+
toolkit_info->deserialize( jo );
421380
}
422381

423382
if( has_flag( "TRANSFORM_TERRAIN" ) || has_flag( "CRASH_TERRAIN_AROUND" ) ) {
424383
if( !transform_terrain_info ) {
425384
transform_terrain_info.emplace();
426385
}
427-
JsonObject jttd = jo.get_object( "transform_terrain" );
428-
vpslot_terrain_transform &vtt = *transform_terrain_info;
429-
optional( jttd, was_loaded, "pre_flags", vtt.pre_flags, {} );
430-
optional( jttd, was_loaded, "post_terrain", vtt.post_terrain );
431-
optional( jttd, was_loaded, "post_furniture", vtt.post_furniture );
432-
if( jttd.has_string( "post_field" ) ) {
433-
mandatory( jttd, was_loaded, "post_field", vtt.post_field );
434-
mandatory( jttd, was_loaded, "post_field_intensity", vtt.post_field_intensity );
435-
mandatory( jttd, was_loaded, "post_field_age", vtt.post_field_age );
436-
}
386+
mandatory( jo, was_loaded, "transform_terrain", transform_terrain_info );
387+
}
388+
}
389+
390+
void vpslot_engine::deserialize( const JsonObject &jo )
391+
{
392+
optional( jo, was_loaded, "backfire_threshold", backfire_threshold, 0.f );
393+
optional( jo, was_loaded, "backfire_freq", backfire_freq, 1 );
394+
optional( jo, was_loaded, "noise_factor", noise_factor, 0 );
395+
optional( jo, was_loaded, "damaged_power_factor", damaged_power_factor, 0.f );
396+
optional( jo, was_loaded, "m2c", m2c, 100 );
397+
optional( jo, was_loaded, "muscle_power_factor", muscle_power_factor, 0 );
398+
optional( jo, was_loaded, "exclusions", exclusions, string_reader{} );
399+
optional( jo, was_loaded, "fuel_options", fuel_opts, string_id_reader<itype> {} );
400+
401+
was_loaded = true;
402+
}
403+
404+
void veh_ter_mod::deserialize( const JsonValue &jv )
405+
{
406+
if( !jv.is_member() ) {
407+
jv.throw_error( "Invalid format" );
408+
}
409+
410+
const JsonMember &jm = dynamic_cast<const JsonMember &>( jv );
411+
JsonArray ja = jm.get_array();
412+
413+
terrain_flag = jm.name();
414+
move_override = ja.get_int( 0 );
415+
move_penalty = ja.get_int( 1 );
416+
}
417+
418+
void vpslot_wheel::deserialize( const JsonObject &jo )
419+
{
420+
optional( jo, was_loaded, "rolling_resistance", rolling_resistance, 1.f );
421+
optional( jo, was_loaded, "contact_area", contact_area, 1 );
422+
optional( jo, was_loaded, "wheel_offroad_rating", offroad_rating, 0.5f );
423+
optional( jo, was_loaded, "wheel_terrain_modifiers", terrain_modifiers,
424+
json_read_reader<veh_ter_mod> {} );
425+
426+
was_loaded = true;
427+
}
428+
429+
void vpslot_rotor::deserialize( const JsonObject &jo )
430+
{
431+
optional( jo, was_loaded, "rotor_diameter", rotor_diameter, 1 );
432+
433+
was_loaded = true;
434+
}
435+
436+
void vpslot_workbench::deserialize( const JsonObject &jo )
437+
{
438+
optional( jo, false, "multiplier", multiplier, 1.f );
439+
optional( jo, false, "mass", allowed_mass, 0_gram );
440+
optional( jo, false, "volume", allowed_volume, 0_ml );
441+
}
442+
443+
void vpslot_toolkit::deserialize( const JsonObject &jo )
444+
{
445+
optional( jo, was_loaded, "allowed_tools", allowed_types, string_id_reader<itype> {} );
446+
447+
was_loaded = true;
448+
}
449+
450+
void vpslot_terrain_transform::deserialize( const JsonObject &jo )
451+
{
452+
optional( jo, false, "pre_flags", pre_flags, {} );
453+
optional( jo, false, "post_terrain", post_terrain );
454+
optional( jo, false, "post_furniture", post_furniture );
455+
if( jo.has_string( "post_field" ) ) {
456+
mandatory( jo, false, "post_field", post_field );
457+
mandatory( jo, false, "post_field_intensity", post_field_intensity );
458+
mandatory( jo, false, "post_field_age", post_field_age );
437459
}
438460
}
439461

src/veh_type.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
class Character;
2828
class JsonObject;
2929
class JsonOut;
30+
class JsonValue;
3031
class vehicle;
3132
class vpart_info;
3233
struct vehicle_prototype;
@@ -122,6 +123,8 @@ enum vpart_bitflags : int {
122123
};
123124

124125
struct vpslot_engine {
126+
bool was_loaded = false;
127+
125128
float backfire_threshold = 0.0f;
126129
int backfire_freq = 1;
127130
int muscle_power_factor = 0;
@@ -130,23 +133,39 @@ struct vpslot_engine {
130133
int m2c = 100;
131134
std::vector<std::string> exclusions;
132135
std::vector<itype_id> fuel_opts;
136+
137+
void deserialize( const JsonObject &jo );
133138
};
134139

135140
struct veh_ter_mod {
136141
std::string terrain_flag; // terrain flag this mod block applies to
137142
int move_override; // override when on flagged terrain, ignored if 0
138143
int move_penalty; // penalty added when not on flagged terrain, ignored if 0
144+
145+
void deserialize( const JsonValue &jv );
146+
// for generic_factory delete/extend
147+
bool operator==( const veh_ter_mod &rhs ) const {
148+
return terrain_flag == rhs.terrain_flag;
149+
}
139150
};
140151

141152
struct vpslot_wheel {
153+
bool was_loaded = false;
154+
142155
float rolling_resistance = 1.0f;
143156
int contact_area = 1;
144157
std::vector<veh_ter_mod> terrain_modifiers;
145158
float offroad_rating = 0.5f;
159+
160+
void deserialize( const JsonObject &jo );
146161
};
147162

148163
struct vpslot_rotor {
164+
bool was_loaded = false;
165+
149166
int rotor_diameter = 1;
167+
168+
void deserialize( const JsonObject &jo );
150169
};
151170

152171
struct vpslot_workbench {
@@ -155,10 +174,16 @@ struct vpslot_workbench {
155174
// Mass/volume allowed before a crafting speed penalty is applied
156175
units::mass allowed_mass = 0_gram;
157176
units::volume allowed_volume = 0_ml;
177+
178+
void deserialize( const JsonObject &jo );
158179
};
159180

160181
struct vpslot_toolkit {
182+
bool was_loaded = false;
183+
161184
std::set<itype_id> allowed_types;
185+
186+
void deserialize( const JsonObject &jo );
162187
};
163188

164189
struct vpslot_terrain_transform {
@@ -169,11 +194,15 @@ struct vpslot_terrain_transform {
169194
//Both only defined if(post_field)
170195
int post_field_intensity;
171196
time_duration post_field_age;
197+
198+
void deserialize( const JsonObject &jo );
172199
};
173200

174201
struct vp_control_req {
175202
std::set<std::pair<skill_id, int>> skills;
176203
std::set<proficiency_id> proficiencies;
204+
205+
void deserialize( const JsonObject &jo );
177206
};
178207

179208
class vpart_category

0 commit comments

Comments
 (0)