-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgenerate_natives.rb
executable file
·470 lines (406 loc) · 17.1 KB
/
generate_natives.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
NATIVES_H = "../../inc/natives.h"
WITH_TICK_CHECK = true
natives = Hash.new{|h,k| h[k] = {}}
current_namespace = nil
File.open(NATIVES_H,"r") do |f|
f.each_line do |line|
line.strip!
if matches = line.match(/\Anamespace (\w+)/)
current_namespace = matches[1]
end
next if !line.match(/\Astatic /)
_, return_type, name, args = *line.match(%r{static ([A-Za-z0-9*]+) (\w+)\(([^\)]*)\)}i)
args = args.split(/, ?/).map do |arg|
{
type: arg.split(" ")[0],
name: arg.split(" ")[1],
}
end
natives[current_namespace][name] = {
return_type: return_type,
arguments: args
}
end
end
def return_for_type(type)
case type
when "void"
"return mrb_nil_value();"
when "BOOL"
"return mrb_bool_value(r0);"
when "int", "Any"
"return mrb_fixnum_value(r0);"
when "float"
"return mrb_float_value(mrb,r0);"
when "Player" # player can be 0, so exclude this from the nil check
<<-CPP
mrb_value rret = mrb_obj_new(mrb, mrb_class_get_under(mrb, mrb_module_get(mrb, "GTAV"), "#{type}"), 0, NULL);
(void)mrb_funcall(mrb, rret, "__load", 1, mrb_fixnum_value(r0));
return rret;
CPP
when "Ped", "Entity", "Vehicle", "Hash", "Blip", "Cam","ScrHandle","Pickup", "Object"
<<-CPP
if(r0 == 0) {
return mrb_nil_value();
} else {
mrb_value rret = mrb_obj_new(mrb, mrb_class_get_under(mrb, mrb_module_get(mrb, "GTAV"), "#{type}"), 0, NULL);
(void)mrb_funcall(mrb, rret, "__load", 1, mrb_fixnum_value(r0));
return rret;
}
CPP
when "Vector3"
<<-CPP
mrb_value rvector3 = mrb_obj_new(mrb, mrb_class_get_under(mrb, mrb_module_get(mrb, "GTAV"), "Vector3"), 0, NULL);
(void)mrb_funcall(mrb, rvector3, "__load", 3, mrb_float_value(mrb, r0.x), mrb_float_value(mrb, r0.y), mrb_float_value(mrb, r0.z));
return rvector3;
CPP
when "char*"
<<-CPP
return mrb_str_new_cstr(mrb,cstr);
CPP
else
raise "unknown type #{type}"
end
end
def cassigns_for_type(type)
case type
when "void"
""
when "Any", "Vector3", "Player", "Ped", "Entity", "Vehicle", "Hash", "Blip", "Cam","ScrHandle","Pickup", "Object"
"#{type} r0 = "
when "float"
"mrb_float r0 = "
when "int"
"mrb_int r0 = "
when "BOOL"
"mrb_bool r0 = "
when "char*"
"char* cstr = "
else
raise "unknown type #{type}"
end
end
def mrb_value_defines(arguments)
defs = []
chars = []
cargs = []
crargs = []
arguments.each_with_index do |arg,i|
mrb_types, mrb_char, n_cargs, n_crargs = mrb_type_and_char(arg,i)
defs += mrb_types
chars << mrb_char
cargs += n_cargs
crargs += n_crargs
end
[defs.join("\n "),chars.join(""),cargs.join(", "),crargs.join(", ")]
end
def mrb_type_and_char(arg,i)
case arg[:type].to_s
when "char*"
[["char* a#{i};","int a#{i}_size;"],"s",["(a#{i}_size == 0 ? 0 : a#{i})"],["&a#{i}, &a#{i}_size"]]
when "BOOL"
[["mrb_bool a#{i};"],"b",["a#{i}"],["&a#{i}"]]
when "float"
[["mrb_float a#{i};"],"f",["a#{i}"],["&a#{i}"]]
when "Vehicle*","Ped*","Entity*","Any*"
[["#{arg[:type].gsub("*","")} a#{i};"],"i",["&a#{i}"],["&a#{i}"]]
when "intp"
[["int a#{i};"],"i",["a#{i}"],["&a#{i}"]]
else
[["mrb_int a#{i};"],"i",["a#{i}"],["&a#{i}"]]
end
end
def tick_check
"\n if(call_limit_enabled && (call_limit-- < 0)) mrb_raise(mrb, mrb_class_get(mrb,\"CallLimitExceeded\"), \"\");"
end
$defined_functions = {}
module_defines = []
$function_bodies = []
$mrb_defines = []
def define_native(mname,fname,argc,body)
cname = "mruby__#{mname}__#{fname}"
mrb_args_def = "MRB_ARGS_NONE()"
mrb_args_def = "MRB_ARGS_REQ(#{argc})" if argc > 0
$defined_functions["#{mname}::#{fname}"] = true
$mrb_defines << "mrb_define_method(mrb, module_#{mname.downcase}, \"#{fname}\", #{cname}, #{mrb_args_def});"
$function_bodies << <<-CPP
mrb_value #{cname}(mrb_state *mrb, mrb_value self) {#{WITH_TICK_CHECK ? tick_check : ""}
#{body}
}
CPP
end
def define_native_multireturn(mname,fname,in_types,out_types,assign,cargs,assign_return,return_nil_if = nil)
cname = "mruby__#{mname}__#{fname}"
mrb_args_def = "MRB_ARGS_NONE()"
mrb_args_def = "MRB_ARGS_REQ(#{in_types.size})" if in_types.size > 0
in_type_chars = ""
in_type_vars = []
in_type_assigns = in_types.each_with_index.map{|t,i|
tt = mrb_type_and_char({type: t},i)
in_type_vars << tt[3].join(",")
in_type_chars << tt[1]
tt[0].join("\n ")
}.join("\n ")
out_type_defs = Array(out_types).each_with_index.map{|t,i|
case t
when :int
"int r#{i};"
when :float
"float r#{i};"
when :char
"char* r#{i};"
when :BOOL
"BOOL r#{i};"
else
"#{t} r#{i};"
end
}.join("\n ")
rarray_i = 0
if assign
assign = "#{assign} r = "
end
if assign_return
assign_return = "mrb_ary_set(mrb,rarray,#{rarray_i},#{include_assign});\n "
end
if out_types.is_a?(Array)
rarray_sets = out_types.each_with_index.map {|t,i|
s = case t
when :int
"mrb_ary_set(mrb,rarray,#{rarray_i},mrb_fixnum_value(r#{i}));"
when :float
"mrb_ary_set(mrb,rarray,#{rarray_i},mrb_float_value(mrb,r#{i}));"
when :BOOL
"mrb_ary_set(mrb,rarray,#{rarray_i},mrb_bool_value(r#{i}));"
when :Vector3
s = []
s << "mrb_value r#{i}v = mrb_obj_new(mrb, mrb_class_get_under(mrb, mrb_module_get(mrb, \"GTAV\"), \"Vector3\"), 0, NULL);"
s << "(void)mrb_funcall(mrb, r#{i}v, \"__load\", 3, mrb_float_value(mrb, r#{i}.x), mrb_float_value(mrb, r#{i}.y), mrb_float_value(mrb, r#{i}.z));"
s << "mrb_ary_set(mrb,rarray,#{rarray_i},r#{i}v);"
# puts s
# s << "mrb_ary_set(mrb,rarray,#{rarray_i},mrb_float_value(mrb,r#{i}.x));"
# rarray_i += 1
# s << "mrb_ary_set(mrb,rarray,#{rarray_i},mrb_float_value(mrb,r#{i}.y));"
# rarray_i += 1
# s << "mrb_ary_set(mrb,rarray,#{rarray_i},mrb_float_value(mrb,r#{i}.z));"
s.join("\n ")
else
"mrb_ary_set(mrb,rarray,#{rarray_i},mrb_fixnum_value(r#{i}));"
end
rarray_i += 1
s
}.join("\n ")
return_statement = <<-CPP
mrb_value rarray = mrb_ary_new_capa(mrb,#{rarray_i});
#{assign_return}
#{rarray_sets}
return rarray;
CPP
else
return_statement = case out_types
when :int
"return mrb_fixnum_value(r0);"
when :float
"return mrb_float_value(mrb,r0);"
when :BOOL
"return mrb_bool_value(r0);"
when :Vector3
<<-CPP
mrb_value rret = mrb_obj_new(mrb, mrb_class_get_under(mrb, mrb_module_get(mrb, "GTAV"), "#{out_types}"), 0, NULL);
(void)mrb_funcall(mrb, rret, "__load", 3, mrb_float_value(mrb,r0.x), mrb_float_value(mrb,r0.y), mrb_float_value(mrb,r0.z));
return rret;
CPP
else
assign_return = nil
<<-CPP
mrb_value rret = mrb_obj_new(mrb, mrb_class_get_under(mrb, mrb_module_get(mrb, "GTAV"), "#{out_types}"), 0, NULL);
(void)mrb_funcall(mrb, rret, "__load", 1, mrb_fixnum_value(r0));
return rret;
CPP
end
end
if return_nil_if
return_statement = <<-CPP
if(#{return_nil_if}){
return mrb_nil_value();
} else {
#{return_statement}
}
CPP
end
if return_nil_if === true
return_statement = "return mrb_nil_value();"
end
mrb_get_args = "mrb_get_args(mrb,\"#{in_type_chars}\",#{in_type_vars.join(",")});"
mrb_get_args = "" if in_types.size == 0
$defined_functions["#{mname}::#{fname}"] = true
$mrb_defines << "mrb_define_class_method(mrb, module_#{mname.downcase}, \"#{fname}\", #{cname}, #{mrb_args_def});"
$function_bodies << <<-CPP
mrb_value #{cname}(mrb_state *mrb, mrb_value self) {#{WITH_TICK_CHECK ? tick_check : ""}
#{in_type_assigns}
#{mrb_get_args}
#{out_type_defs}
#{assign}#{mname}::#{fname}(#{cargs});
#{return_statement}
}
CPP
end
define_native("GRAPHICS","_WORLD3D_TO_SCREEN2D",3,<<-CPP)
mrb_float a0;
mrb_float a1;
mrb_float a2;
mrb_get_args(mrb,"fff",&a0,&a1,&a2);
float r0;
float r1;
GRAPHICS::_WORLD3D_TO_SCREEN2D(a0,a1,a2,&r0,&r1);
if(r0 < 0.0 && r1 < 0.0) {
return mrb_nil_value();
} else {
mrb_value rarray = mrb_ary_new_capa(mrb,2);
mrb_ary_set(mrb,rarray,0,mrb_float_value(mrb,r0));
mrb_ary_set(mrb,rarray,1,mrb_float_value(mrb,r1));
return rarray;
}
CPP
# n(mname,fname,in_types,out_types,assign,cargs)
define_native_multireturn("PLAYER","GET_PLAYER_RGB_COLOUR",[:Player],[:int,:int,:int],nil,"a0,&r0,&r1,&r2",nil)
define_native_multireturn("PLAYER","GET_PLAYER_TARGET_ENTITY",[:Player],:Entity,"BOOL","a0,&r0",nil,"!r")
define_native_multireturn("PLAYER","GET_ENTITY_PLAYER_IS_FREE_AIMING_AT",[:Player],:Entity,"BOOL","a0,&r0",nil,"!r")
define_native_multireturn("PLAYER","GET_PLAYER_PARACHUTE_TINT_INDEX",[:Player],:int,nil,"a0,&r0",nil,"r0 == -1")
define_native_multireturn("PLAYER","GET_PLAYER_RESERVE_PARACHUTE_TINT_INDEX",[:Player],:int,nil,"a0,&r0",nil,"r0 == -1")
define_native_multireturn("PLAYER","GET_PLAYER_PARACHUTE_PACK_TINT_INDEX",[:Player],:int,nil,"a0,&r0",nil,"r0 == -1")
define_native_multireturn("PLAYER","GET_PLAYER_PARACHUTE_SMOKE_TRAIL_COLOR",[:Player],[:int,:int,:int],nil,"a0,&r0,&r1,&r2",nil,nil)
define_native_multireturn("PED","GET_PED_LAST_DAMAGE_BONE",[:Ped],:Any,nil,"a0,&r0",nil,nil)
define_native_multireturn("PED","GET_GROUP_SIZE",[:int],[:Any,:int],nil,"a0,&r0,&r1",nil,nil)
define_native_multireturn("PED","IS_PED_EVASIVE_DIVING",[:Ped],:Entity,"BOOL","a0,&r0",nil,"!r")
define_native_multireturn("ENTITY","GET_ENTITY_MATRIX",[:Entity],[:Any,:Any,:Vector3,:Vector3],nil,"a0,&r0,&r1,&r2,&r3",nil,nil)
define_native_multireturn("ENTITY","GET_ENTITY_QUATERNION",[:Entity],[:float,:float,:float,:float],nil,"a0,&r0,&r1,&r2,&r3",nil,nil)
define_native_multireturn("ENTITY","SET_OBJECT_AS_NO_LONGER_NEEDED",[:Entity],[],nil,"(Object*) &a0",nil,true)
define_native_multireturn("OBJECT","DELETE_OBJECT",[:Entity],[],nil,"(Object*) &a0",nil,true)
define_native_multireturn("VEHICLE","GET_VEHICLE_CUSTOM_PRIMARY_COLOUR",[:Vehicle],[:int,:int,:int],nil,"a0,&r0,&r1,&r2",nil,nil)
define_native_multireturn("VEHICLE","GET_VEHICLE_CUSTOM_SECONDARY_COLOUR",[:Vehicle],[:int,:int,:int],nil,"a0,&r0,&r1,&r2",nil,nil)
define_native_multireturn("VEHICLE","GET_VEHICLE_COLOURS",[:Vehicle],[:int,:int],nil,"a0,&r0,&r1",nil,nil)
define_native_multireturn("VEHICLE","GET_VEHICLE_LIGHTS_STATE",[:Vehicle],[:int,:int],nil,"a0,&r0,&r1",nil,nil)
define_native_multireturn("VEHICLE","GET_RANDOM_VEHICLE_MODEL_IN_MEMORY",[:BOOL],[:Hash,:int],nil,"a0,&r0,&r1",nil,nil)
define_native_multireturn("VEHICLE","GET_VEHICLE_EXTRA_COLOURS",[:Vehicle],[:int,:int],nil,"a0,&r0,&r1",nil,nil)
define_native_multireturn("VEHICLE","GET_VEHICLE_TRAILER_VEHICLE",[:Vehicle],:Vehicle,"BOOL","a0,&r0",nil,"!r")
define_native_multireturn("VEHICLE","GET_VEHICLE_MOD_COLOR_1",[:Vehicle],[:int,:int,:int],nil,"a0,&r0,&r1,&r2",nil,nil)
define_native_multireturn("VEHICLE","GET_VEHICLE_MOD_COLOR_2",[:Vehicle],[:int,:int],nil,"a0,&r0,&r1",nil,nil)
define_native_multireturn("VEHICLE","GET_VEHICLE_TYRE_SMOKE_COLOR",[:Vehicle],[:int,:int,:int],nil,"a0,&r0,&r1,&r2",nil,nil)
define_native_multireturn("VEHICLE","GET_VEHICLE_COLOR",[:Vehicle],[:int,:int,:int],nil,"a0,&r0,&r1,&r2",nil,nil)
define_native_multireturn("VEHICLE","_GET_VEHICLE_NEON_LIGHTS_COLOUR",[:Vehicle],[:int,:int,:int],nil,"a0,&r0,&r1,&r2",nil,nil)
define_native_multireturn("VEHICLE","_GET_VEHICLE_OWNER",[:Vehicle],:Entity,"BOOL","a0,&r0",nil,"!r")
define_native_multireturn("GRAPHICS","GET_SCREEN_RESOLUTION",[],[:int,:int],nil,"&r0,&r1",nil,nil)
define_native_multireturn("GRAPHICS","_GET_SCREEN_ACTIVE_RESOLUTION",[],[:int,:int],nil,"&r0,&r1",nil,nil)
define_native_multireturn("GRAPHICS","SET_SCALEFORM_MOVIE_AS_NO_LONGER_NEEDED",[:intp],[],nil,"&a0",nil,nil)
define_native_multireturn("GAMEPLAY","GET_MODEL_DIMENSIONS",[:Hash],[:Vector3,:Vector3],nil,"a0,&r0,&r1",nil,nil)
define_native_multireturn("GAMEPLAY","GET_GROUND_Z_FOR_3D_COORD",[:float,:float,:float,:BOOL],:float,nil,"a0,a1,a2,&r0,a3",nil,nil)
define_native_multireturn("GAMEPLAY","_GET_WEATHER_TYPE_TRANSITION",[],[:Any,:Any,:float],nil,"&r0,&r1,&r2",nil,nil)
define_native_multireturn("WEAPON","GET_CURRENT_PED_WEAPON",[:Ped,:BOOL],:Hash,"BOOL","a0,&r0,a1",nil,"!r")
define_native_multireturn("WEAPON","GET_CURRENT_PED_VEHICLE_WEAPON",[:Ped],:Hash,"BOOL","a0,&r0",nil,"!r")
define_native_multireturn("WEAPON","GET_AMMO_IN_CLIP",[:Ped,:Hash],:int,"BOOL","a0,a1,&r0",nil,"!r")
define_native_multireturn("WEAPON","GET_MAX_AMMO",[:Ped,:Hash],:int,"BOOL","a0,a1,&r0",nil,"!r")
define_native_multireturn("WEAPON","GET_PED_LAST_WEAPON_IMPACT_COORD",[:Ped],:Vector3,"BOOL","a0,&r0",nil,"!r")
define_native_multireturn("STATS","STAT_GET_INT",[:Hash,:int],:int,"BOOL","a0,&r0,a1",nil,"!r")
define_native_multireturn("STATS","STAT_GET_FLOAT",[:Hash,:Any],:float,"BOOL","a0,&r0,a1",nil,"!r")
define_native_multireturn("STATS","STAT_GET_BOOL",[:Hash,:Any],:BOOL,"BOOL","a0,&r0,a1",nil,"!r")
define_native_multireturn("UI","REMOVE_BLIP",[:Blip],[],nil,"(Blip*) &a0",nil,true)
define_native_multireturn("UI","GET_HUD_COLOUR",[:int],[:int,:int,:int,:int],nil,"a0,&r0,&r1,&r2,&r3",nil,nil)
define_native_multireturn("PATHFIND","GET_STREET_NAME_AT_COORD",[:float,:float,:float],[:Hash,:Hash],nil,"a0,a1,a2,&r0,&r1",nil,nil)
natives.each_pair do |mname,namespace|
module_defines << "struct RClass *module_#{mname.downcase} = mrb_define_module(mrb, \"#{mname}\");"
namespace.each_pair do |fname,definition|
gen = true
# next unless ["PED","ENTITY","GRAPHICS","VEHICLE","PLAYER"].include?( mname )
# gen = false unless ["void","Player","Ped","Vector3","Vehicle","Entity","int","float","BOOL","Hash","Any","Blip","Cam","ScrHandle","Pickup","char*","Object"].include?( definition[:return_type] )
# next unless [0,4].include?( definition[:arguments].size )
gen = false if ["Any*"].include?( definition[:return_type] )
gen = false unless definition[:arguments].all?{|a| ["Entity","float","BOOL","int","Ped","Player","Vehicle","Entity","Any","Object","Hash","Blip","Cam","ScrHandle","Pickup","char*","Vehicle*","Ped*","Entity*","Any*"].include?(a[:type]) }
gen = false unless definition[:arguments].each_with_index.all?{|a,i| ["Vehicle*","Ped*","Entity*","Any*"].include?(a[:type]) ? i == 0 : true }
# puts [mname,fname,definition].inspect
if !gen && !$defined_functions["#{mname}::#{fname}"]
puts "// not generating #{mname}::#{fname} - #{definition.inspect}"
next
end
if $defined_functions["#{mname}::#{fname}"]
next
end
cname = "mruby__#{mname}__#{fname}"
mrb_args_def = "MRB_ARGS_NONE()"
mrb_get_args = nil
mrb_value_defs, mrb_chars, cargs, crargs = mrb_value_defines(definition[:arguments])
if definition[:arguments].size > 0
mrb_get_args = "mrb_get_args(mrb,\"#{mrb_chars}\",#{crargs});"
mrb_args_def = "MRB_ARGS_REQ(#{definition[:arguments].size})"
end
$mrb_defines << "mrb_define_method(mrb, module_#{mname.downcase}, \"#{fname}\", #{cname}, #{mrb_args_def});"
$function_bodies << <<-CPP
mrb_value #{cname}(mrb_state *mrb, mrb_value self) {#{WITH_TICK_CHECK ? tick_check : ""}#{"\n "+mrb_value_defs+"\n" if mrb_value_defs.size > 0}#{" "+mrb_get_args+"" if mrb_get_args}
#{cassigns_for_type(definition[:return_type])}#{mname}::#{fname}(#{cargs});
#{return_for_type(definition[:return_type]).chomp}
}
CPP
end
end
# define_native("PLAYER","GET_PLAYER_RGB_COLOUR",1,<<-CPP)
# mrb_int a0;
# mrb_get_args(mrb,"i",&a0);
# int r0;
# int r1;
# int r2;
# PLAYER::GET_PLAYER_RGB_COLOUR(a0,&r0,&r1,&r2);
# mrb_value rarray = mrb_ary_new_capa(mrb,3);
# mrb_ary_set(mrb,rarray,0,mrb_fixnum_value(r0));
# mrb_ary_set(mrb,rarray,1,mrb_fixnum_value(r1));
# mrb_ary_set(mrb,rarray,1,mrb_fixnum_value(r2));
# return rarray;
# CPP
template = <<-CPP
/*
THIS FILE IS A PART OF GTA V SCRIPT HOOK SDK
http://dev-c.com
(C) Alexander Blade 2015
*/
#include "script.h"
#include "utils.h"
#include "keyboard.h"
#include <io.h>
#include <string.h>
#include <fcntl.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "mruby.h"
#include "mruby/irep.h"
#include "mruby/array.h"
#include "mruby/value.h"
#include "mruby/numeric.h"
#include "mruby/string.h"
#ifdef __cplusplus
}
#endif
static int call_limit_enabled = 0;
static int call_limit = 1000;
#{$function_bodies.join("\n")}
void mruby_install_natives(mrb_state *mrb) {
#{module_defines.join("\n ")}
#{$mrb_defines.join("\n ")}
}
mrb_value mruby__gtav__set_call_limit(mrb_state *mrb, mrb_value self) {
mrb_int a0;
mrb_get_args(mrb,"i",&a0);
if(a0 == -1){
call_limit_enabled = 0;
} else {
call_limit_enabled = 1;
}
call_limit = a0;
return mrb_nil_value();
}
mrb_value mruby__gtav__get_call_limit(mrb_state *mrb, mrb_value self) {
return mrb_fixnum_value(call_limit);
}
CPP
print template
generated = $function_bodies.size
total = natives.values.map(&:size).inject(0){|a,i| a + i}
puts "// generated #{generated} out of #{total} native functions (#{total - generated} ungenerated)"