blob: a2ec3cd47cd1b15173450bf1aa32359c4c634231 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// * living_name-Behandlung
2
Zesstracd25d262020-01-21 19:36:39 +01003#include "/sys/userinfo.h"
4
MG Mud User88f12472016-06-24 23:31:02 +02005#define clean_log(s)
6//#define clean_log(s) log_file("CLEAN_SIM",ctime(time())[4..18]+": "+(s));
7
8private nosave mapping living_name_m, name_living_m, netdead;
9
10private void InitLivingData(mixed wizinfo) {
11 // living_name ist ein Pointer der auch in der extra_wizinfo gehalten
12 // wird, so kann die simul_efun neu geladen werden, ohne dass dieses
13 // Mapping verloren geht
14 if (!mappingp(living_name_m = wizinfo[LIVING_NAME]))
15 living_name_m = wizinfo[LIVING_NAME] = m_allocate(0, 1);
16
17 // Gleiches gilt fuer das Mapping Name-Living
18 if (!mappingp(name_living_m = wizinfo[NAME_LIVING]))
19 name_living_m = wizinfo[NAME_LIVING] = m_allocate(0, 1);
20
21 // Netztote sind ebenfalls in der extra_wizinfo
22 if (!mappingp(netdead = wizinfo[NETDEAD_MAP]))
23 netdead = wizinfo[NETDEAD_MAP] = ([]);
24}
25
Zesstrafddc2a42020-01-21 22:06:47 +010026public varargs string getuuid( object|string ob )
MG Mud User88f12472016-06-24 23:31:02 +020027{
Zesstrafddc2a42020-01-21 22:06:47 +010028 string uid;
29 if (stringp(ob))
30 uid = ob;
31 else
32 {
33 if ( !objectp(ob) )
34 ob = previous_object();
35 uid = getuid(ob);
Zesstra2d9fef62020-01-22 22:10:54 +010036 if (!query_once_interactive(ob))
37 return uid;
Zesstrafddc2a42020-01-21 22:06:47 +010038 }
MG Mud User88f12472016-06-24 23:31:02 +020039
Zesstra2d9fef62020-01-22 22:10:54 +010040 // sollte <uid> kein Spieler-UID sein, ist creation 0 und es wird die <uid>
Zesstrafddc2a42020-01-21 22:06:47 +010041 // unveraendert zurueckgeben.
42 int creation = master()->query_userlist(uid, USER_CREATION_DATE);
MG Mud User88f12472016-06-24 23:31:02 +020043
Zesstra311f9702020-01-21 22:08:56 +010044 if (!creation)
Zesstrafddc2a42020-01-21 22:06:47 +010045 return uid;
MG Mud User88f12472016-06-24 23:31:02 +020046
Zesstracd25d262020-01-21 19:36:39 +010047 // Username + "_" + CreationDate
Zesstrafddc2a42020-01-21 22:06:47 +010048 return uid + "_" + creation;
MG Mud User88f12472016-06-24 23:31:02 +020049}
50
51void set_object_living_name(string livname, object obj)
52{
53 string old;
54 mixed a;
55 int i;
56
57 if (previous_object()==obj || previous_object()==this_object() ||
58 previous_object()==master())
59 {
60 if(!livname || !stringp(livname)) {
61 set_this_object(previous_object());
62 raise_error(sprintf("%O: illegal living name: %O\n", obj, livname));
63 }
64 if (old = living_name_m[obj]) {
65 if (pointerp(a = name_living_m[old])) {
66 a[member(a, obj)] = 0;
67 } else {
68 m_delete(name_living_m, old);
69 }
70 }
71 living_name_m[obj] = livname;
72 if (a = name_living_m[livname]) {
73 if (!pointerp(a)) {
74 name_living_m[livname] = ({a, obj});
75 return;
76 }
77 /* Try to reallocate entry from destructed object */
78 if ((i = member(a, 0)) >= 0) {
79 a[i] = obj;
80 return;
81 }
82 name_living_m[livname] = a + ({obj});
83 return;
84 }
85 name_living_m[livname] = obj;
86 }
87}
88
89void set_living_name(string livname)
90{
91 set_object_living_name(livname,previous_object());
92}
93
94void remove_living_name()
95{
96 string livname;
97
98 if (!previous_object())
99 return;
100 if (livname=living_name_m[previous_object()])
101 {
102 m_delete(living_name_m,previous_object());
103 if (objectp(name_living_m[livname]))
104 {
105 if (name_living_m[livname]==previous_object())
106 m_delete(name_living_m,livname);
107 return;
108 }
109 if (pointerp(name_living_m[livname]))
110 {
111 name_living_m[livname]-=({previous_object()});
112 if (!sizeof(name_living_m[livname]))
113 m_delete(name_living_m,livname);
114 }
115 }
116}
117
118void _set_netdead()
119{
120 if (query_once_interactive(previous_object()))
121 netdead[getuid(previous_object())]=previous_object();
122}
123
124void _remove_netdead()
125{
126 m_delete(netdead,getuid(previous_object()));
127}
128
129object find_netdead(string uuid)
130{
131 int i;
132 string uid;
133 // Wenn sscanf() 2 liefert, ist uuid auch ne uuid.
134 int is_uuid = sscanf(uuid, "%s_%d", uid, i) == 2;
135 if (!is_uuid)
136 uid = uuid;
137
138 if (is_uuid && getuuid(netdead[uid]) != uuid)
139 return 0;
140
141 return netdead[uid];
142}
143
144string *dump_netdead()
145{
146 return m_indices(netdead);
147}
148
149object find_living(string livname) {
150 mixed *a, r;
151 int i;
152
153 if (pointerp(r = name_living_m[livname])) {
154 if (member(r,0)>=0)
155 r-=({0});
156 if (!sizeof(r)){
157 m_delete(name_living_m,livname);
158 clean_log(sprintf("find_living loescht %s\n",livname));
159 return 0;
160 }
161 if ( !living(r = (a = r)[0])) {
162 for (i = sizeof(a); --i;) {
163 if (living(a[<i])) {
164 r = a[<i];
165 a[<i] = a[0];
166 return a[0] = r;
167 }
168 }
169 }
170 return r;
171 }
172 return living(r) && r;
173}
174
175object *find_livings(string livname)
176{
177 mixed r;
178
179 if (pointerp(r=name_living_m[livname]))
180 r-=({0});
181 else
182 if (objectp(r))
183 r=({r});
184 if (!pointerp(r)||!sizeof(r))
185 return 0;
Arathorn235d75b2021-02-28 11:44:57 +0100186 return copy(r);
MG Mud User88f12472016-06-24 23:31:02 +0200187}
188
189object find_player(string uuid) {
190 object *objs;
191 mixed res;
192 int i;
193 string uid;
194
195 if (!stringp(uuid))
196 return 0;
197 // Wenn sscanf() 2 liefert, ist uuid auch ne uuid.
198 int is_uuid = sscanf(uuid, "%s_%d", uid, i) == 2;
199 if (!is_uuid)
200 uid = uuid;
201
202 if (pointerp(res = name_living_m[uid])) {
203 // zerstoerte Objekte ggf. entfernen
204 if (member(res,0)>=0) {
205 res-=({0});
206 name_living_m[uid] = res;
207 }
208 // ggf. Namen ohne Objekte entfernen.
209 if (!sizeof(res)){
210 m_delete(name_living_m,uid);
211 clean_log(sprintf("find_player loescht %s\n",uid));
212 return 0;
213 }
214 objs = res;
215 res = objs[0];
216 // Wenn das 0. Element der Spieler ist, sind wir fertig. Ansonsten suchen
217 // wir den Spieler und schieben ihn an die 0. Stelle im Array.
218 if ( !query_once_interactive(res)) {
219 for (i = sizeof(objs); --i;) {
220 if (objs[<i] && query_once_interactive(objs[<i])) {
221 res = objs[<i];
222 objs[<i] = objs[0];
223 objs[0] = res;
224 break;
225 }
226 }
227 res = (objectp(res) && query_once_interactive(res)) ? res : 0;
228 }
229 // else: in res steht der Spieler schon.
230 }
231 else if (objectp(res)) // r ist nen Einzelobjekt
232 res = query_once_interactive(res) ? res : 0;
233
234 // res ist jetzt ggf. der Spieler. Aber wenn der ne andere als die gesuchte
235 // UUID hat, ist das Ergebnis trotzdem 0.
236 if (is_uuid && getuuid(res)!=uuid)
237 return 0;
238
239 // endlich gefunden
240 return res;
241}
242
243private int check_match( string str, int players_only )
244{
245 mixed match;
246
247 if ( !(match = name_living_m[str]) )
248 return 0;
249
250 if ( !pointerp(match) )
251 match = ({ match });
252
253 match -= ({0});
254
255 if ( sizeof(match) ){
256 if ( players_only )
257 return sizeof(filter( match, #'query_once_interactive/*'*/ ))
258 > 0;
259 else
260 return 1;
261 }
262
263 m_delete( name_living_m, str );
264 clean_log( sprintf("check_match loescht %s\n", str) );
265 return 0;
266}
267
268//TODO:: string|string* exclude
269varargs mixed match_living( string str, int players_only, mixed exclude )
270{
271 int i, s;
272 mixed match, *user;
273
274 if ( !str || str == "" )
275 return 0;
276
277 if ( !pointerp(exclude) )
278 exclude = ({ exclude });
279
280 if ( member(exclude, str) < 0 && check_match(str, players_only) )
281 return str;
282
283 user = m_indices(name_living_m);
284 s = sizeof(str);
285 match = 0;
286
287 for ( i = sizeof(user); i--; )
288 if ( str == user[i][0..s-1] && member( exclude, user[i] ) < 0 )
289 if ( match )
290 return -1;
291 else
292 if ( check_match(user[i], players_only) )
293 match = user[i];
294
295 if ( !match )
296 return -2;
297
298 return match;
299}
300
301mixed *dump_livings()
302{
303 return sort_array(m_indices(name_living_m),#'>);
304}
305
306// * regelmaessig Listen von Ballast befreien
307private void clean_name_living_m(string *keys, int left, int num)
308{
309 int i, j;
310 mixed a;
311
312 while (left && num--)
313 {
314 if (pointerp(a = name_living_m[keys[--left]]) && member(a, 0)>=0)
315 {
316 a-=({0});
317 name_living_m[keys[left]] = a;
318 }
319 if (!a || (pointerp(a) && !sizeof(a)))
320 {
321 clean_log("Toasting "+keys[left]+"\n");
322 m_delete(name_living_m, keys[left]);
323 } else clean_log(sprintf("KEEPING %s (%O)\n",keys[left],pointerp(a)?sizeof(a):a));
324 }
325 if (left)
326 efun::call_out(#'clean_name_living_m, 1, keys, left, 80);
327 else
328 clean_log("Clean process finished\n");
329}
330
331private void clean_netdead() {
332 int i;
333 string *s;
334 object ob;
335
336 s=m_indices(netdead);
337 for (i=sizeof(s)-1;i>=0;i--)
338 if (!objectp(ob=netdead[s[i]]) || interactive(ob))
339 m_delete(netdead,s[i]);
340}
341
342private void CleanLivingData() {
343 if (find_call_out(#'clean_name_living_m) < 0) {
344 clean_log("Starting clean process\n");
345 efun::call_out(#'clean_name_living_m,
346 1,
347 m_indices(name_living_m),
348 sizeof(name_living_m),
349 80
350 );
351 }
352 efun::call_out(#'clean_netdead,2);
353}
354
355#undef clean_log
356