]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/debug.qh
s/make_pure/new_pure/
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / debug.qh
1 #pragma once
2
3 #ifndef MENUQC
4 .bool debug;
5 .int sv_entnum;
6 REGISTER_NET_TEMP(net_debug)
7 #endif
8
9 #ifdef SVQC
10
11 #include <server/command/all.qh>
12
13 #endif
14
15 #ifdef CSQC
16         NET_HANDLE(net_debug, bool isNew)
17         {
18                 Net_Accept(net_debug);
19                 this.sv_entnum = ReadShort();
20                 if (ReadByte()) make_pure(this);
21                 this.origin_x = ReadCoord();
22                 this.origin_y = ReadCoord();
23                 this.origin_z = ReadCoord();
24                 setorigin(this, this.origin);
25                 this.debug = true;  // identify server entities by this
26                 this.classname = strzone(ReadString());
27                 this.sourceLoc = strzone(ReadString());
28                 return true;
29         }
30 #endif
31
32 #ifdef SVQC
33         bool debug_send(entity this, entity to, int sf)
34         {
35                 int channel = MSG_ONE;
36                 msg_entity = to;
37                 WriteHeader(channel, net_debug);
38                 WriteShort(channel, etof(this));
39                 WriteByte(channel, is_pure(this));
40                 vector o = this.origin;
41                 if (o == '0 0 0') // brushes
42                         o = (this.absmin + this.absmax) / 2;
43                 if (this.tag_entity)
44                         o += this.tag_entity.origin;
45                 WriteCoord(channel, o.x); WriteCoord(channel, o.y); WriteCoord(channel, o.z);
46                 WriteString(channel, this.classname);
47                 WriteString(channel, this.sourceLoc);
48                 return true;
49         }
50 #endif
51
52 #ifndef MENUQC
53 /**
54  * 0: off
55  * 1: on
56  * 2: on (pure)
57  * 3: on (.entnum != 0)
58  * 4: on (.origin == '0 0 0')
59  * 5: on (.debug != 0), server only
60  * 6: on (.solid != 0)
61  */
62 bool autocvar_debugdraw;
63 #endif
64
65 #ifdef CSQC
66         string autocvar_debugdraw_filter, autocvar_debugdraw_filterout;
67         .int debugdraw_last;
68         vector project_3d_to_2d(vector vec);
69         void Debug_Draw()
70         {
71                 if (!autocvar_debugdraw) return;
72                 static int debugdraw_frame;
73                 ++debugdraw_frame;
74                 const int sz = 8;
75                 FOREACH_ENTITY(true, LAMBDA(
76                         if (it.debugdraw_last == debugdraw_frame) continue;
77                         int ofs = 0;
78                         for (entity e = findradius(it.origin, 100); e; e = e.chain)
79                         {
80                                 if (e.debugdraw_last == debugdraw_frame) continue;
81                                 e.debugdraw_last = debugdraw_frame;
82                                 vector rgb = (e.debug) ? '0 0 1' : '1 0 0';
83                                 if (autocvar_debugdraw_filterout != "" && strhasword(autocvar_debugdraw_filterout, e.classname)) continue;
84                                 if (autocvar_debugdraw_filter != "" && !strhasword(autocvar_debugdraw_filter, e.classname)) continue;
85                                 if (autocvar_debugdraw == 3)
86                                 {
87                                         if (!e.entnum) continue;
88                                 }
89                                 if (autocvar_debugdraw == 4)
90                                 {
91                                         if (e.origin) continue;
92                                 }
93                                 if (autocvar_debugdraw == 5)
94                                 {
95                                         if (!e.debug) continue;
96                                 }
97                                 else if (autocvar_debugdraw > 5)
98                                 {
99                                         bool flag = true;
100                                         do {
101 //                                              if (e.modelindex) break;
102 //                                              if (e.absmin) break;
103 //                                              if (e.absmax) break;
104 //                                              if (e.entnum) break;
105 //                                              if (e.drawmask) break;
106 //                                              if (e.predraw) break;
107 //                                              if (e.movetype) break;
108                                                 if (e.solid) break;
109 //                                              if (e.origin) break;
110 //                                              if (e.oldorigin) break;
111 //                                              if (e.velocity) break;
112 //                                              if (e.angles) break;
113 //                                              if (e.avelocity) break;
114 //                                              if (e.classname) break;
115 //                                              if (e.model) break;
116 //                                              if (e.frame) break;
117 //                                              if (e.skin) break;
118 //                                              if (e.effects) break;
119 //                                              if (e.mins) break;
120 //                                              if (e.maxs) break;
121 //                                              if (e.size) break;
122 //                                              if (e.touch) break;
123 //                                              if (e.use) break;
124 //                                              if (e.think) break;
125 //                                              if (e.blocked) break;
126 //                                              if (e.nextthink) break;
127 //                                              if (e.chain) break;
128 //                                              if (e.netname) break;
129 //                                              if (e.enemy) break;
130 //                                              if (e.flags) break;
131 //                                              if (e.colormap) break;
132 //                                              if (e.owner) break;
133                                                 flag = false;
134                                         } while (0);
135                                         if (!flag) continue;
136                                 }
137                                 else if (is_pure(e))
138                                 {
139                                         if (autocvar_debugdraw < 2) continue;
140                                         rgb.y = 1;
141                                 }
142                                 vector o = e.origin;
143                                 if (e.tag_entity)
144                                         o += e.tag_entity.origin;
145                                 vector pos = project_3d_to_2d(o);
146                                 if (pos.z < 0) continue;
147                                 pos.z = 0;
148                                 pos.y += ofs * sz;
149                                 drawcolorcodedstring2(pos,
150                                         sprintf("%d: '%s'@%s", (e.debug ? e.sv_entnum : etof(e)),
151                                         e.classname, e.sourceLoc),
152                                         sz * '1 1 0', rgb, 0.5, DRAWFLAG_NORMAL);
153                                 ++ofs;
154                         }
155                 ));
156         }
157 #endif
158
159 #ifdef SVQC
160         COMMON_COMMAND(debugdraw_sv, "Dump all server entities")
161         {
162                 switch (request)
163                 {
164                         case CMD_REQUEST_COMMAND:
165                         {
166                                 if (!autocvar_debugdraw) return;
167                                 int n = 1000;
168                                 int rem = n;
169                                 for (entity e = NULL; (e = findfloat(e, debug, 0)) && rem > 0; )
170                                 {
171                                         if (autocvar_debugdraw < 2 && is_pure(e)) continue;
172                                         debug_send(e, caller, 0);
173                                         e.debug = true;
174                                         --rem;
175                                 }
176                                 LOG_INFOF("%d server entities sent\n", n - rem);
177                                 return;
178                         }
179
180                         default:
181                         case CMD_REQUEST_USAGE:
182                         {
183                                 LOG_INFO(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " debugdraw_sv"));
184                                 return;
185                         }
186                 }
187         }
188 #endif
189
190 GENERIC_COMMAND(bufstr_get, "Examine a string buffer object")
191 {
192         switch (request)
193         {
194                 case CMD_REQUEST_COMMAND:
195                 {
196                         int bufhandle = stof(argv(1));
197                         int string_index = stof(argv(2));
198                         string s = bufstr_get(bufhandle, string_index);
199                         LOG_INFOF("%s\n", s);
200                         return;
201                 }
202
203                 default:
204                 case CMD_REQUEST_USAGE:
205                 {
206                         LOG_INFO(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " bufstr_get bufhandle string_index"));
207                         return;
208                 }
209         }
210 }
211
212 GENERIC_COMMAND(version, "Print the current version")
213 {
214         switch (request)
215         {
216                 case CMD_REQUEST_COMMAND:
217                 {
218                         LOG_INFO(WATERMARK "\n");
219                         return;
220                 }
221                 default:
222                 case CMD_REQUEST_USAGE:
223                 {
224                         LOG_INFO(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " version"));
225                         return;
226                 }
227         }
228 }
229
230 REGISTER_STAT(TRACE_ENT, int)
231 #ifdef SVQC
232 bool autocvar_debugtrace;
233
234 REGISTER_MUTATOR(trace, autocvar_debugtrace);
235
236 .bool debug_trace_button;
237 .int solid_prev;
238 MUTATOR_HOOKFUNCTION(trace, SV_StartFrame)
239 {
240         FOREACH_CLIENT(true, {
241                 bool skip = false;
242                 bool btn = PHYS_INPUT_BUTTON_HOOK(it);
243                 if (btn == it.debug_trace_button) skip = true;
244                 it.debug_trace_button = btn;
245                 if (!btn || skip) continue;
246                 FOREACH_ENTITY(true, {
247                     it.solid_prev = it.solid;
248                         it.solid = SOLID_BBOX;
249                 });
250                 vector forward; vector right; vector up;
251                 MAKEVECTORS(makevectors, it.v_angle, forward, right, up);
252                 vector pos = it.origin + it.view_ofs;
253                 traceline(pos, pos + forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, it);
254                 FOREACH_ENTITY(true, {
255                     it.solid = it.solid_prev;
256             it.solid_prev = 0;
257                 });
258                 entity e = trace_ent;
259                 int i = etof(e);
260                 STAT(TRACE_ENT, it) = i;
261                 if (!e) continue;
262                 setorigin(e, e.origin + '0 0 100');
263                 stuffcmd(it, sprintf("prvm_edict server %d\n", i));
264         });
265 }
266 #endif
267 #ifdef CSQC
268 entity TRACE_ENT;
269 void Trace_draw2d(entity this)
270 {
271         int e = STAT(TRACE_ENT);
272         if (!e) return;
273         vector pos = '0 0 0';
274         pos.y += vid_conheight / 2;
275         drawstring(pos, sprintf("prvm_edict server %d", e), '10 10 0', '1 1 1', 1, DRAWFLAG_NORMAL);
276 }
277
278 STATIC_INIT(TRACE_ENT)
279 {
280         entity e = TRACE_ENT = new_pure(TRACE_ENT);
281         e.draw2d = Trace_draw2d;
282 }
283 #endif
284
285 #ifdef SVQC
286 SERVER_COMMAND(find, "Search through entities for matching classname")
287 {
288         switch (request)
289         {
290                 case CMD_REQUEST_COMMAND:
291                 {
292                         for (entity client = NULL; (client = find(client, classname, argv(1))); )
293                                 LOG_INFO(etos(client), "\n");
294                         return;
295                 }
296
297                 default:
298                         LOG_INFO("Incorrect parameters for ^2find^7\n");
299                 case CMD_REQUEST_USAGE:
300                 {
301                         LOG_INFO("\nUsage:^3 sv_cmd find classname\n");
302                         LOG_INFO("  Where 'classname' is the classname to search for.\n");
303                         return;
304                 }
305         }
306 }
307
308 SERVER_COMMAND(findat, "Search through entities for matching origin")
309 {
310         switch (request)
311         {
312                 case CMD_REQUEST_COMMAND:
313                 {
314                     vector match = stov(argv(1));
315                     FOREACH_ENTITY_ORDERED(it.origin == match, LAMBDA(LOG_INFOF("%i\n", it)));
316                         return;
317                 }
318
319                 default:
320                         LOG_INFO("Incorrect parameters for ^2findat^7\n");
321                 case CMD_REQUEST_USAGE:
322                 {
323                         LOG_INFO("\nUsage:^3 sv_cmd findat \"0 0 0\"\n");
324                         return;
325                 }
326         }
327 }
328 #endif