1 #ifndef _API_PARAM_H_ 2 #define _API_PARAM_H_ 3 4 /** @file api_param.h templates for transfer of function call parameters */ 5 6 #include "../squirrel/squirrel.h" 7 #include "../simobj.h" 8 #include "../simtypes.h" 9 #include "../tpl/quickstone_tpl.h" 10 #include "../utils/cbuffer_t.h" 11 12 class baum_t; 13 class convoi_t; 14 class fabrik_t; 15 class factory_supplier_desc_t; 16 class factory_product_desc_t; 17 class gebaeude_t; 18 class grund_t; 19 class haltestelle_t; 20 class karte_t; 21 class karte_ptr_t; 22 class koord; 23 class koord3d; 24 class label_t; 25 class loadsave_t; 26 struct schedule_entry_t; 27 struct my_ribi_t; 28 struct my_slope_t; 29 class planquadrat_t; 30 class plainstring; 31 class scenario_t; 32 class schedule_t; 33 class settings_t; 34 class simline_t; 35 class player_t; 36 class stadt_t; 37 class tool_t; 38 class ware_production_t; 39 class weg_t; 40 class way_builder_t; 41 42 /** 43 * @namespace script_api The namespace contains all functions necessary to communicate 44 * between simutrans and squirrel: transfer parameters, export classes and functions. 45 * 46 * @brief API simutrans <-> squirrel 47 */ 48 namespace script_api { 49 /// pointer to the world 50 extern karte_ptr_t welt; 51 52 // forward declaration 53 struct mytime_t; 54 struct mytime_ticks_t; 55 56 /** 57 * Cannot specialize templates by void, so use own void type 58 */ 59 struct void_t {}; 60 61 /** 62 * Templated interface to transfer variables from / to squirrel. 63 */ 64 template<class T> struct param { 65 /** 66 * Gets parameters for calls to c++ functions from stack. 67 * @param index on stack 68 * @return value of parameter 69 */ 70 #ifdef DOXYGEN 71 static T get(HSQUIRRELVM vm, SQInteger index); 72 #endif 73 74 /** 75 * Pushes parameters for calls to squirrel functions on stack. 76 * @return positive value for success, negative for failure 77 */ 78 #ifdef DOXYGEN 79 static SQInteger push(HSQUIRRELVM vm, T const& v); 80 #endif 81 /// typemask: this squirrel type needs to be provided when calling c++ function typemaskparam82 static const char* typemask() { return "."; } 83 84 /// squirrel_type corresponding to the c++ type/class squirrel_typeparam85 static const char* squirrel_type() { return "any_x"; } 86 }; 87 88 /** 89 * Create slots in table/class on the stack: 90 * it has the same effect as 'table.name <- value'. 91 * @tparam type of the new value 92 * @param name name of the slot to be created 93 * @param value value to be set 94 * @param static_ true if this should be a static class member 95 * @param index of table/instance/etc on the stack 96 * @returns positive value on success, negative on failure 97 */ 98 template<class T> 99 SQInteger create_slot(HSQUIRRELVM vm, const char* name, T const& value, bool static_ = false, SQInteger index = -1) 100 { 101 sq_pushstring(vm, name, -1); 102 if (SQ_SUCCEEDED(param<T>::push(vm, value))) { 103 SQInteger new_index = index > 0 ? index : index-2; 104 return sq_newslot(vm, new_index, static_); 105 } 106 else { 107 sq_pop(vm, 1); /* pop name */ 108 return SQ_ERROR; 109 } 110 } 111 112 /** 113 * Sets value to existing variable in table, instance etc at index @p index. 114 * @tparam type of the new value 115 * @param name name of the slot to be created 116 * @param value value to be set 117 * @param index of table/instance/etc on the stack 118 * @returns positive value on success, negative on failure 119 */ 120 template<class T> 121 SQInteger set_slot(HSQUIRRELVM vm, const char* name, T const& value, SQInteger index = -1) 122 { 123 sq_pushstring(vm, name, -1); 124 if (SQ_SUCCEEDED(param<T>::push(vm, value))) { 125 SQInteger new_index = index > 0 ? index : index-2; 126 return sq_set(vm, new_index); 127 } 128 else { 129 sq_pop(vm, 1); /* pop name */ 130 return SQ_ERROR; 131 } 132 } 133 134 /** 135 * Gets value to existing variable in table, instance etc at index @p index. 136 * @tparam type of the new value 137 * @param name name of the slot to be created 138 * @param value will be set upon success 139 * @param index of table/instance/etc on the stack 140 * @returns positive value on success, negative on failure 141 */ 142 template<class T> 143 SQInteger get_slot(HSQUIRRELVM vm, const char* name, T& value, SQInteger index = -1) 144 { 145 sq_pushstring(vm, name, -1); 146 SQInteger new_index = index > 0 ? index : index-1; 147 if (SQ_SUCCEEDED(sq_get(vm, new_index))) { 148 value = param<T>::get(vm, -1); 149 sq_pop(vm, 1); 150 return SQ_OK; 151 } 152 return SQ_ERROR; 153 } 154 155 /** 156 * partial specialization for 'const T*' types 157 */ 158 template<class T> struct param<const T*> { 159 /** 160 * Gets parameters for calls to c++ functions from stack. 161 * @param index on stack 162 * @return value of parameter 163 */ 164 static const T* get(HSQUIRRELVM vm, SQInteger index) 165 { 166 return param<T*>::get(vm, index); 167 } 168 /** 169 * Pushes parameters for calls to squirrel functions on stack. 170 * @return positive value for success, negative for failure 171 */ 172 static SQInteger push(HSQUIRRELVM vm, const T* const& v) 173 { 174 return param<T*>::push(vm, v); 175 } 176 177 /// typemask: this squirrel type needs to be provided when calling c++ function 178 static const char* typemask() 179 { 180 return param<T*>::typemask(); 181 } 182 /// squirrel_type corresponding to the c++ type/class 183 static const char* squirrel_type() 184 { 185 return param<T*>::squirrel_type(); 186 } 187 }; 188 189 /** 190 * partial specialization for 'const T' types 191 */ 192 template<class T> struct param<const T> { 193 /** 194 * Gets parameters for calls to c++ functions from stack. 195 * @param index on stack 196 * @return value of parameter 197 */ 198 static const T get(HSQUIRRELVM vm, SQInteger index) 199 { 200 return param<T>::get(vm, index); 201 } 202 /** 203 * Pushes parameters for calls to squirrel functions on stack. 204 * @return positive value for success, negative for failure 205 */ 206 static SQInteger push(HSQUIRRELVM vm, T const& v) 207 { 208 return param<T>::push(vm, v); 209 } 210 211 /// typemask: this squirrel type needs to be provided when calling c++ function 212 static const char* typemask() 213 { 214 return param<T>::typemask(); 215 } 216 /// squirrel_type corresponding to the c++ type/class 217 static const char* squirrel_type() 218 { 219 return param<T>::squirrel_type(); 220 } 221 }; 222 223 /** 224 * partial specialization for 'const T&' types 225 */ 226 template<class T> struct param<const T&> { 227 /** 228 * Pushes parameters for calls to squirrel functions on stack. 229 * @return positive value for success, negative for failure 230 */ 231 static SQInteger push(HSQUIRRELVM vm, const T& v) 232 { 233 return param<T>::push(vm, v); 234 } 235 236 /// typemask: this squirrel type needs to be provided when calling c++ function 237 static const char* typemask() 238 { 239 return param<T>::typemask(); 240 } 241 /// squirrel_type corresponding to the c++ type/class 242 static const char* squirrel_type() 243 { 244 return param<T>::squirrel_type(); 245 } 246 }; 247 248 /** 249 * partial specialization for container types 250 */ 251 template< template<class> class vector, class T> struct param< vector<T> > { 252 /** 253 * Pushes parameters for calls to squirrel functions on stack. 254 * @return positive value for success, negative for failure 255 */ 256 static SQInteger push(HSQUIRRELVM vm, vector<T> const& v) 257 { 258 sq_newarray(vm, 0); 259 260 FORT(const vector<T>, const&i, v) { 261 param<T>::push(vm, i); 262 sq_arrayappend(vm, -2); 263 } 264 return 1; 265 } 266 /// squirrel_type corresponding to the c++ type/class 267 static const char* squirrel_type() 268 { 269 static cbuffer_t buf; 270 buf.clear(); 271 buf.printf("array<%s>", param<T>::squirrel_type() ); 272 return buf; 273 } 274 }; 275 276 /** 277 * partial specialization for *handle_t types 278 */ 279 // declared here, implementation in api_class.h, 280 // which has to be included if necessary 281 template<class T> struct param< quickstone_tpl<T> >; 282 283 284 #define declare_types(mask, sqtype) \ 285 static const char* typemask() { return mask; } \ 286 static const char* squirrel_type() \ 287 { \ 288 return sqtype; \ 289 } 290 291 /// macro to declare specialized param template 292 #define declare_specialized_param(T, mask, sqtype) \ 293 template<> struct param<T> { \ 294 static T get(HSQUIRRELVM vm, SQInteger index); \ 295 static SQInteger push(HSQUIRRELVM vm, T const& v);\ 296 static void* tag(); \ 297 declare_types(mask, sqtype); \ 298 }; 299 /// macro to only define typemask for specialized param template 300 /// if only 'const class*' is defined then parameter mask must be defined for 'class *' too. 301 #define declare_param_mask(T, mask, sqtype) \ 302 template<> struct param<T> { \ 303 declare_types(mask, sqtype) \ 304 }; 305 /// macro to declare fake types, inherited from void_t, 306 /// for documentation purposes 307 #define declare_fake_param(T, sqtype) \ 308 class T { public: T(void_t) {}; operator void_t() const { return void_t();} }; \ 309 template<> struct param<T> { \ 310 static T get(HSQUIRRELVM vm, SQInteger index) { return param<void_t>::get(vm, index); } \ 311 static SQInteger push(HSQUIRRELVM vm, T const& v) { return param<void_t>::push(vm, v); } \ 312 declare_types(".", sqtype); \ 313 }; 314 // macro to declare enums 315 #define declare_enum_param(T, inttype, sqtype) \ 316 template<> struct param<T> { \ 317 static T get(HSQUIRRELVM vm, SQInteger index) { return (T)param<inttype>::get(vm, index); } \ 318 static SQInteger push(HSQUIRRELVM vm, T const& v) { return param<inttype>::push(vm, v); } \ 319 declare_types("i", sqtype); \ 320 }; 321 322 323 324 declare_specialized_param(void_t, ".", "void"); 325 // no typemask, as we call to_bool 326 declare_specialized_param(bool, ".", "bool"); 327 328 declare_specialized_param(uint8, "i", "integer"); 329 declare_specialized_param(sint8, "i", "integer"); 330 declare_specialized_param(uint16, "i", "integer"); 331 declare_specialized_param(sint16, "i", "integer"); 332 declare_specialized_param(uint32, "i", "integer"); 333 declare_specialized_param(sint32, "i", "integer"); 334 declare_specialized_param(uint64, "i", "integer"); 335 declare_specialized_param(sint64, "i", "integer"); 336 declare_enum_param(waytype_t, sint16, "way_types"); 337 declare_enum_param(systemtype_t, uint8, "way_system_types"); 338 declare_enum_param(obj_t::typ, uint8, "map_objects"); 339 declare_enum_param(climate, uint8, "climates"); 340 declare_specialized_param(my_ribi_t, "i", "dir"); 341 declare_specialized_param(my_slope_t, "i", "slope"); 342 343 declare_specialized_param(double, "i|f", "float"); 344 345 declare_specialized_param(const char*, ".", "string"); 346 // no string typemask, as we call to_string 347 declare_specialized_param(plainstring, ".", "string"); 348 349 declare_specialized_param(koord, "t|x|y", "coord"); 350 declare_specialized_param(koord3d, "t|x|y", "coord3d"); 351 352 declare_specialized_param(convoi_t*, "t|x|y", "convoy_x"); 353 declare_specialized_param(fabrik_t*, "t|x|y", "factory_x"); 354 declare_specialized_param(grund_t*, "t|x|y", "tile_x"); 355 declare_specialized_param(const haltestelle_t*, "t|x|y", "halt_x"); 356 declare_param_mask(haltestelle_t*, "t|x|y", "halt_x"); 357 declare_specialized_param(karte_t*, ".", "world"); 358 declare_specialized_param(planquadrat_t*, "t|x|y", "square_x"); 359 declare_specialized_param(settings_t*, "t|x|y", "settings"); 360 declare_specialized_param(schedule_t*, "t|x|y", "schedule_x"); 361 declare_specialized_param(const schedule_t*, "t|x|y", "schedule_x"); 362 declare_specialized_param(schedule_entry_t, "t|x|y", "schedule_entry_x"); 363 declare_specialized_param(mytime_t, "i|t|x|y", "time_x"); 364 declare_specialized_param(mytime_ticks_t, "i|t|x|y", "time_ticks_x"); 365 declare_specialized_param(scenario_t*, "t|x|y", ""); 366 declare_specialized_param(simline_t*, "t|x|y", "line_x"); 367 declare_specialized_param(player_t*, "t|x|y", "player_x"); 368 declare_specialized_param(stadt_t*, "t|x|y", "city_x"); 369 declare_specialized_param(const ware_production_t*, "t|x|y", "factory_production_x"); 370 declare_specialized_param(const factory_supplier_desc_t*, "t|x|y", "factory_production_x"); 371 declare_specialized_param(const factory_product_desc_t*, "t|x|y", "factory_production_x"); 372 declare_param_mask(ware_production_t*, "t|x|y", "factory_production_x"); 373 declare_specialized_param(tool_t*, "x", "command_x"); 374 declare_specialized_param(way_builder_t*, "t|x|y", "way_planner_x"); 375 376 // export of obj_t derived classes in api/map_objects.cc 377 declare_specialized_param(obj_t*, "t|x|y", "map_object_x"); 378 declare_specialized_param(baum_t*, "t|x|y", "tree_x"); 379 declare_specialized_param(gebaeude_t*, "t|x|y", "building_x"); 380 declare_specialized_param(label_t*, "t|x|y", "label_x"); 381 declare_specialized_param(weg_t*, "t|x|y", "way_x"); 382 383 /** 384 * Returns the player associated to the script 385 * (or NULL for scenarios) 386 */ 387 player_t* get_my_player(HSQUIRRELVM vm); 388 389 /** 390 * Templated interface to declare free variables for 391 * c++ function calls 392 */ 393 template<class A1> struct freevariable { 394 A1 arg1; 395 freevariable(A1 const& a1) : arg1(a1) {} 396 397 /** 398 * Pushes the free variables 399 * @returns number of pushed parameters 400 */ 401 SQInteger push(HSQUIRRELVM vm) const { 402 SQInteger count = 0; 403 if (SQ_SUCCEEDED( param<A1>::push(vm, arg1) ) ) count++; 404 return count; 405 } 406 }; 407 408 /** 409 * Templated interface to declare free variables for 410 * c++ function calls 411 */ 412 template<class A1,class A2> struct freevariable2 : public freevariable<A1> { 413 A2 arg2; 414 freevariable2(A1 const& a1, A2 const& a2) : freevariable<A1>(a1), arg2(a2) {} 415 416 /** 417 * Pushes the free variables 418 * @returns number of pushed parameters 419 */ 420 SQInteger push(HSQUIRRELVM vm) const { 421 SQInteger count = 0; 422 if (SQ_SUCCEEDED( param<A2>::push(vm, arg2) ) ) count++; 423 count += freevariable<A1>::push(vm); 424 return count; 425 } 426 }; 427 428 template<class A1,class A2,class A3> struct freevariable3 : public freevariable2<A1,A2> { 429 A3 arg3; 430 freevariable3(A1 const& a1, A2 const& a2, A3 const& a3) : freevariable2<A1,A2>(a1,a2), arg3(a3) {} 431 432 /** 433 * Pushes the free variables 434 * @returns number of pushed parameters 435 */ 436 SQInteger push(HSQUIRRELVM vm) const { 437 SQInteger count = 0; 438 if (SQ_SUCCEEDED( param<A3>::push(vm, arg3) ) ) count++; 439 count += freevariable2<A1,A2>::push(vm); 440 return count; 441 } 442 }; 443 444 445 /** 446 * Static class to handle the translation of world coordinates (which are sensible to rotation) 447 * to script coordinates (that are independent of rotation). 448 */ 449 class coordinate_transform_t { 450 private: 451 /// Stores how many times initial map was rotated. 452 /// Scripts do not take care of rotated maps. 453 /// Coordinates will be translated between in-game coordinates and script coordinates. 454 /// First v.m. to be started sets this value 455 static uint8 rotation; 456 public: 457 /// called if a new world is initialized 458 static void new_world() { rotation=4; /*invalid*/ } 459 460 /// inits rotation from karte_t::settings 461 static void initialize(); 462 463 /// keep track of rotation 464 static void rotate90() { if (rotation<4) rotation = (rotation+1)&3; } 465 466 /// read/save rotation to stay consistent after saving & loading 467 static void rdwr(loadsave_t*); 468 469 /** 470 * rotate actual world coordinates back, 471 * coordinates after transform are like in the 472 * scenario's original savegame 473 */ 474 static void koord_w2sq(koord &); 475 476 /** 477 * rotate original coordinates to actual world coordinates 478 */ 479 static void koord_sq2w(koord &); 480 481 /** 482 * rotate actual world coordinates direction to original direction 483 */ 484 static void ribi_w2sq(ribi_t::ribi &r); 485 486 /** 487 * rotate original direction to actual world coordinates direction 488 */ 489 static void ribi_sq2w(ribi_t::ribi &r); 490 491 /** 492 * rotate actual slope to original slope 493 */ 494 static void slope_w2sq(slope_t::type &s); 495 496 /** 497 * rotate original slope to actual slope 498 */ 499 static void slope_sq2w(slope_t::type &s); 500 501 static uint8 get_rotation() { return rotation; } 502 }; 503 504 /// called by karte_t directly 505 void rotate90(); 506 /// called by karte_t directly 507 void new_world(); 508 509 }; // end of namespace 510 #endif 511